From a09ea75d801a35c2c4785ed218d3881da4d88f8d Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Fri, 27 Aug 2021 13:29:41 +0300 Subject: [PATCH] SDL port v1, Windows only for now. Working: graphics, sound, music (3dpb only). Not working: GUI, user settings. --- .gitignore | 6 + CMakeLists.txt | 145 + CMakeSettings.json | 27 + README.md | 6 +- SpaceCadetPinball.sln | 31 - SpaceCadetPinball/Sound.cpp | 242 +- SpaceCadetPinball/Sound.h | 20 +- SpaceCadetPinball/SpaceCadetPinball.cpp | 4 +- SpaceCadetPinball/SpaceCadetPinball.vcxproj | 316 -- .../SpaceCadetPinball.vcxproj.filters | 441 --- SpaceCadetPinball/TPinballTable.cpp | 7 +- SpaceCadetPinball/WaveMix.cpp | 2627 ----------------- SpaceCadetPinball/WaveMix.h | 244 -- SpaceCadetPinball/control.cpp | 40 +- SpaceCadetPinball/fullscrn.cpp | 2 +- SpaceCadetPinball/gdrv.cpp | 95 +- SpaceCadetPinball/gdrv.h | 5 +- SpaceCadetPinball/high_score.cpp | 4 +- SpaceCadetPinball/loader.cpp | 2 +- SpaceCadetPinball/loader.h | 3 +- SpaceCadetPinball/midi.cpp | 63 +- SpaceCadetPinball/midi.h | 7 +- SpaceCadetPinball/options.cpp | 24 +- SpaceCadetPinball/pb.cpp | 6 +- SpaceCadetPinball/pb.h | 2 +- SpaceCadetPinball/pch.h | 7 + SpaceCadetPinball/pinball.cpp | 218 +- SpaceCadetPinball/score.cpp | 19 +- SpaceCadetPinball/winmain.cpp | 429 ++- SpaceCadetPinball/winmain.h | 2 + 30 files changed, 872 insertions(+), 4172 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 CMakeSettings.json delete mode 100644 SpaceCadetPinball.sln delete mode 100644 SpaceCadetPinball/SpaceCadetPinball.vcxproj delete mode 100644 SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters delete mode 100644 SpaceCadetPinball/WaveMix.cpp delete mode 100644 SpaceCadetPinball/WaveMix.h diff --git a/.gitignore b/.gitignore index 0e6b0e2..0af0471 100644 --- a/.gitignore +++ b/.gitignore @@ -263,3 +263,9 @@ __pycache__/ /Export /DrMem /Doc private +# Windows local libraries +/Libs + +#CMake generated +out/ +/cmake-build-debug diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..15cfc2e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,145 @@ +cmake_minimum_required(VERSION 3.16) +project(SpaceCadetPinball) + +set(CMAKE_CXX_STANDARD 14) + +set(SDL2_DIR "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2-2.0.16") +set(SDL2_mixer_DIR "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2_mixer-2.0.4") + + +find_package(SDL2 REQUIRED) +FIND_PACKAGE(SDL2_mixer REQUIRED) + + +include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS}) + +set(SOURCE_FILES + SpaceCadetPinball/control.cpp + SpaceCadetPinball/control.h + SpaceCadetPinball/fullscrn.cpp + SpaceCadetPinball/fullscrn.h + SpaceCadetPinball/gdrv.cpp + SpaceCadetPinball/gdrv.h + SpaceCadetPinball/high_score.cpp + SpaceCadetPinball/high_score.h + SpaceCadetPinball/loader.cpp + SpaceCadetPinball/loader.h + SpaceCadetPinball/maths.cpp + SpaceCadetPinball/maths.h + SpaceCadetPinball/memory.cpp + SpaceCadetPinball/memory.h + SpaceCadetPinball/midi.cpp + SpaceCadetPinball/midi.h + SpaceCadetPinball/nudge.cpp + SpaceCadetPinball/nudge.h + SpaceCadetPinball/objlist_class.h + SpaceCadetPinball/options.cpp + SpaceCadetPinball/options.h + SpaceCadetPinball/partman.cpp + SpaceCadetPinball/partman.h + SpaceCadetPinball/pb.cpp + SpaceCadetPinball/pb.h + SpaceCadetPinball/pch.cpp + SpaceCadetPinball/pch.h + SpaceCadetPinball/pinball.cpp + SpaceCadetPinball/pinball.h + SpaceCadetPinball/proj.cpp + SpaceCadetPinball/proj.h + SpaceCadetPinball/render.cpp + SpaceCadetPinball/render.h + SpaceCadetPinball/resource.h + SpaceCadetPinball/score.cpp + SpaceCadetPinball/score.h + SpaceCadetPinball/Sound.cpp + SpaceCadetPinball/Sound.h + SpaceCadetPinball/SpaceCadetPinball.cpp + SpaceCadetPinball/splash.cpp + SpaceCadetPinball/splash.h + SpaceCadetPinball/TBall.cpp + SpaceCadetPinball/TBall.h + SpaceCadetPinball/TBlocker.cpp + SpaceCadetPinball/TBlocker.h + SpaceCadetPinball/TBumper.cpp + SpaceCadetPinball/TBumper.h + SpaceCadetPinball/TCircle.cpp + SpaceCadetPinball/TCircle.h + SpaceCadetPinball/TCollisionComponent.cpp + SpaceCadetPinball/TCollisionComponent.h + SpaceCadetPinball/TComponentGroup.cpp + SpaceCadetPinball/TComponentGroup.h + SpaceCadetPinball/TDemo.cpp + SpaceCadetPinball/TDemo.h + SpaceCadetPinball/TDrain.cpp + SpaceCadetPinball/TDrain.h + SpaceCadetPinball/TEdgeBox.cpp + SpaceCadetPinball/TEdgeBox.h + SpaceCadetPinball/TEdgeManager.cpp + SpaceCadetPinball/TEdgeManager.h + SpaceCadetPinball/TEdgeSegment.cpp + SpaceCadetPinball/TEdgeSegment.h + SpaceCadetPinball/TFlagSpinner.cpp + SpaceCadetPinball/TFlagSpinner.h + SpaceCadetPinball/TFlipper.cpp + SpaceCadetPinball/TFlipper.h + SpaceCadetPinball/TFlipperEdge.cpp + SpaceCadetPinball/TFlipperEdge.h + SpaceCadetPinball/TGate.cpp + SpaceCadetPinball/TGate.h + SpaceCadetPinball/THole.cpp + SpaceCadetPinball/THole.h + SpaceCadetPinball/timer.cpp + SpaceCadetPinball/timer.h + SpaceCadetPinball/TKickback.cpp + SpaceCadetPinball/TKickback.h + SpaceCadetPinball/TKickout.cpp + SpaceCadetPinball/TKickout.h + SpaceCadetPinball/TLight.cpp + SpaceCadetPinball/TLight.h + SpaceCadetPinball/TLightBargraph.cpp + SpaceCadetPinball/TLightBargraph.h + SpaceCadetPinball/TLightGroup.cpp + SpaceCadetPinball/TLightGroup.h + SpaceCadetPinball/TLightRollover.cpp + SpaceCadetPinball/TLightRollover.h + SpaceCadetPinball/TLine.cpp + SpaceCadetPinball/TLine.h + SpaceCadetPinball/TOneway.cpp + SpaceCadetPinball/TOneway.h + SpaceCadetPinball/TPinballComponent.cpp + SpaceCadetPinball/TPinballComponent.h + SpaceCadetPinball/TPinballTable.cpp + SpaceCadetPinball/TPinballTable.h + SpaceCadetPinball/TPlunger.cpp + SpaceCadetPinball/TPlunger.h + SpaceCadetPinball/TPopupTarget.cpp + SpaceCadetPinball/TPopupTarget.h + SpaceCadetPinball/TRamp.cpp + SpaceCadetPinball/TRamp.h + SpaceCadetPinball/TRollover.cpp + SpaceCadetPinball/TRollover.h + SpaceCadetPinball/TSink.cpp + SpaceCadetPinball/TSink.h + SpaceCadetPinball/TSoloTarget.cpp + SpaceCadetPinball/TSoloTarget.h + SpaceCadetPinball/TSound.cpp + SpaceCadetPinball/TSound.h + SpaceCadetPinball/TTableLayer.cpp + SpaceCadetPinball/TTableLayer.h + SpaceCadetPinball/TTextBox.cpp + SpaceCadetPinball/TTextBox.h + SpaceCadetPinball/TTextBoxMessage.cpp + SpaceCadetPinball/TTextBoxMessage.h + SpaceCadetPinball/TTimer.cpp + SpaceCadetPinball/TTimer.h + SpaceCadetPinball/TTripwire.cpp + SpaceCadetPinball/TTripwire.h + SpaceCadetPinball/TWall.cpp + SpaceCadetPinball/TWall.h + SpaceCadetPinball/winmain.cpp + SpaceCadetPinball/winmain.h + SpaceCadetPinball/zdrv.cpp + SpaceCadetPinball/zdrv.h) + +add_executable(SpaceCadetPinball ${SOURCE_FILES}) + +target_link_libraries(SpaceCadetPinball ${SDL2_LIBRARIES} ${SDL2_MIXER_LIBRARIES}) diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000..2fb8251 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,27 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + }, + { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x86" ], + "variables": [] + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 300ed11..dd21e38 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ Compile with Visual Studio; tested with 2017 and 2019. * ~~Resizable window, scaled graphics~~ * ~~Loader for high-res sprites from CADET.DAT~~ * Misc features of Full Tilt: 3 music tracs, multiball, centered textboxes, etc. - * Maybe: cross-platform port - * Needs UI framework with menu bar and dialog windows, like QT or Avalonia - * Needs a way play sounds and midi + * Cross-platform port + * Using SDL2, SDL2_mixer, ImGui + * Maybe: Android port * Maybe x2: support for other two tables * Table specific BL (control interactions and missions) is hardcoded, othere parts might be also patched diff --git a/SpaceCadetPinball.sln b/SpaceCadetPinball.sln deleted file mode 100644 index 8586b4b..0000000 --- a/SpaceCadetPinball.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.705 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.ActiveCfg = Debug|x64 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.Build.0 = Debug|x64 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.ActiveCfg = Debug|Win32 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.Build.0 = Debug|Win32 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.ActiveCfg = Release|x64 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.Build.0 = Release|x64 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.ActiveCfg = Release|Win32 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4B620E0B-FD42-4AEC-BC4A-261C1669A1B5} - EndGlobalSection -EndGlobal diff --git a/SpaceCadetPinball/Sound.cpp b/SpaceCadetPinball/Sound.cpp index 2eb61f9..a1b0993 100644 --- a/SpaceCadetPinball/Sound.cpp +++ b/SpaceCadetPinball/Sound.cpp @@ -3,268 +3,54 @@ #include "pb.h" -#include "pinball.h" -#include "WaveMix.h" -#include "winmain.h" int Sound::num_channels; -HWND Sound::wavemix_window; -HANDLE Sound::pMem; unsigned int Sound::enabled_flag; -int Sound::channel_time[8]; -MIXWAVE* Sound::channel_wavePtr[8]; -void (*Sound::callback_ptr)(int, MIXWAVE*, int); -HMODULE Sound::HInstance; - -int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int)) +int Sound::Init(int voices) { - WNDCLASSA WndClass; - char FileName[300]; - int channelCount = voices; if (voices > 8) channelCount = 8; num_channels = channelCount; - if (wavemix_window || pMem) - return 0; enabled_flag = -1; - for (int i = 0; i < channelCount; ++i) - { - channel_time[i] = 0; - channel_wavePtr[i] = nullptr; - } - callback_ptr = someFuncPtr; - if (!someFuncPtr) - callback_ptr = NullCallback; - pinball::make_path_name(FileName, "wavemix.inf", 300); - FILE* wavemixIniFile = nullptr; - fopen_s(&wavemixIniFile, FileName, "r"); - if (wavemixIniFile) - { - fclose(wavemixIniFile); - } - else - { - /*FT does not have the file, defaults work OK*/ - if (!pb::FullTiltMode) - MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), "", 0x2000u); - } - - WndClass.style = 0; - WndClass.lpfnWndProc = SoundCallBackWndProc; - WndClass.cbClsExtra = 0; - WndClass.cbWndExtra = 0; - WndClass.hInstance = hInstance; - WndClass.hIcon = nullptr; - WndClass.hCursor = nullptr; - WndClass.hbrBackground = nullptr; - WndClass.lpszMenuName = nullptr; - WndClass.lpszClassName = "WaveMixSoundGuy"; - RegisterClassA(&WndClass); - wavemix_window = CreateWindowExA( - 0, - "WaveMixSoundGuy", - nullptr, - 0x80000000, - 0x80000000, - 0, - 0x80000000, - 0, - nullptr, - nullptr, - hInstance, - nullptr); - if (!wavemix_window) - return 0; - - HInstance = hInstance; - HANDLE hMixSession = WaveMix::Init(); - pMem = hMixSession; - if (!hMixSession) - return 0; - WaveMix::OpenChannel(hMixSession, num_channels, 2u); - return 1; + return Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024) == -1; } void Sound::Enable(int channelFrom, int channelTo, int enableFlag) { - if (pMem) - { - if (channelTo >= num_channels) - channelTo = num_channels - 1; - - if (channelFrom >= 0 && channelTo < num_channels) - { - for (int index = channelFrom; index <= channelTo; ++index) - { - int channelFlag = 1 << index; - if (enableFlag) - { - enabled_flag |= channelFlag; - } - else - { - enabled_flag &= ~channelFlag; - Flush(index, index); - } - } - } - } -} - -void Sound::Idle() -{ - if (pMem) - WaveMix::Pump(); + enabled_flag = enableFlag; } void Sound::Activate() { - if (pMem) - WaveMix::Activate(pMem, true); + Mix_Resume(-1); } void Sound::Deactivate() { - if (pMem) - WaveMix::Activate(pMem, false); + Mix_Pause(-1); } void Sound::Close() { - if (wavemix_window) - { - DestroyWindow(wavemix_window); - wavemix_window = nullptr; - } - if (pMem) - { - WaveMix::CloseChannel(pMem, 0, 1); - WaveMix::CloseSession(pMem); - pMem = nullptr; - } + Mix_Quit(); } -void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops) +void Sound::PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops) { - MIXPLAYPARAMS mixParams{}; - - if (!pMem) - return; - - if (maxChannel >= num_channels) - maxChannel = num_channels - 1; - if (!wavePtr || minChannel < 0 || maxChannel >= num_channels) - return; - - if ((dwFlags & 0x8000) != 0 && num_channels > 0) - { - int index2 = 0; - bool ok = false; - while (channel_wavePtr[index2] != wavePtr) - { - if (++index2 >= num_channels) - { - ok = true; - break; - } - } - if (!ok) - return; - } - - - int playChannel = minChannel; - if (minChannel < maxChannel) - { - int curChannel = minChannel; - do - { - ++curChannel; - if ((1 << curChannel) & enabled_flag && - channel_time[curChannel] < channel_time[playChannel]) - { - playChannel = curChannel; - } - } - while (curChannel < maxChannel); - } - - if ((1 << playChannel) & enabled_flag) - { - mixParams.hMixSession = pMem; - mixParams.hWndNotify = wavemix_window; - mixParams.dwFlags = dwFlags; - mixParams.wSize = 28; - mixParams.wLoops = loops; - mixParams.iChannel = playChannel; - mixParams.lpMixWave = wavePtr; - - callback_ptr(1, wavePtr, playChannel); - channel_time[playChannel] = timeGetTime(); - channel_wavePtr[playChannel] = wavePtr; - WaveMix::Play(&mixParams); - } + if (enabled_flag) + Mix_PlayChannel(-1, wavePtr, loops); } -MIXWAVE* Sound::LoadWaveFile(LPCSTR lpName) +Mix_Chunk* Sound::LoadWaveFile(LPCSTR lpName) { - return pMem ? WaveMix::OpenWave(pMem, lpName, HInstance, 1u) : nullptr; + return Mix_LoadWAV(lpName); } -void Sound::FreeSound(MIXWAVE* wave) +void Sound::FreeSound(Mix_Chunk* wave) { - if (wave && pMem) - WaveMix::FreeWave(pMem, wave); -} - -void Sound::Flush(int channelFrom, int channelTo) -{ - if (pMem) - { - if (channelTo >= num_channels) - channelTo = num_channels - 1; - - if (channelFrom >= 0 && channelTo < num_channels) - { - for (auto index = channelFrom; index <= channelTo; index++) - { - WaveMix::FlushChannel(pMem, index, 0); - channel_time[index] = 0; - channel_wavePtr[index] = nullptr; - } - } - } -} - -void Sound::NullCallback(int a1, MIXWAVE* a2, int a3) -{ -} - -LRESULT Sound::SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - if (Msg != MM_WOM_DONE) - return DefWindowProcA(hWnd, Msg, wParam, lParam); - - auto wavePtr = reinterpret_cast(lParam); - int channel = -1; - for (auto index = 0; index < num_channels; ++index) - { - if (channel_wavePtr[index] == wavePtr && - (channel < 0 || channel_time[index] < channel_time[channel])) - { - channel = index; - } - } - - if (channel >= 0) - { - channel_time[channel] = 0; - channel_wavePtr[channel] = nullptr; - } - - callback_ptr(2, wavePtr, channel); - return 0; + if (wave) + Mix_FreeChunk(wave); } diff --git a/SpaceCadetPinball/Sound.h b/SpaceCadetPinball/Sound.h index c599fe5..f0b977b 100644 --- a/SpaceCadetPinball/Sound.h +++ b/SpaceCadetPinball/Sound.h @@ -1,28 +1,18 @@ #pragma once -#include "WaveMix.h" + class Sound { public: - static int Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int)); + static int Init(int voices); static void Enable(int channelFrom, int channelTo, int enableFlag); - static void Idle(); static void Activate(); static void Deactivate(); static void Close(); - static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops); - static MIXWAVE* LoadWaveFile(LPCSTR lpName); - static void FreeSound(MIXWAVE* wave); - static void Flush(int channelFrom, int channelTo); - static void NullCallback(int a1, MIXWAVE* a2, int a3); - static LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + static void PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops); + static Mix_Chunk* LoadWaveFile(LPCSTR lpName); + static void FreeSound(Mix_Chunk* wave); private: static int num_channels; - static HWND wavemix_window; - static HANDLE pMem; static unsigned int enabled_flag; - static int channel_time[8]; - static MIXWAVE* channel_wavePtr[8]; - static void (* callback_ptr)(int, MIXWAVE*, int); - static HMODULE HInstance; }; diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp index a5f3bbe..3d211fe 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.cpp +++ b/SpaceCadetPinball/SpaceCadetPinball.cpp @@ -25,7 +25,7 @@ int main() } std::cout << "Hello World!\n"; - gdrv::init(nullptr, nullptr); + gdrv::init(nullptr,0,0); auto dib = gdrv::DibCreate(8, 1, 1); gdrv::DibSetUsage(dib, nullptr, 1); @@ -39,7 +39,7 @@ int main() auto xx = sizeof(datFileHeader); lstrcpyA(winmain::DatFileName, "PINBALL.DAT"); - pb::init(); + pb::init(nullptr); auto datFile = pb::record_table; assert(partman::field_size_nth(datFile, 0, datFieldTypes::String, 0) == 43); diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj b/SpaceCadetPinball/SpaceCadetPinball.vcxproj deleted file mode 100644 index 1848094..0000000 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {F7B78CC7-6984-4F79-9486-ABCF87DF9F06} - Win32Proj - SpaceCadetPinball - 10.0 - - - - Application - true - v142 - NotSet - - - Application - false - v142 - true - NotSet - - - Application - true - v142 - NotSet - - - Application - false - v142 - true - NotSet - - - - - - - - - - - - - - - - - - - - - true - false - - - true - - - false - - - false - - - - Use - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - true - false - true - - - Console - true - Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies) - - - - - Use - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - true - - - Console - true - Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies) - - - - - Use - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - true - - - Windows - true - true - true - Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies) - - - - - Use - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - true - - - Windows - true - true - true - Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters deleted file mode 100644 index 89692b0..0000000 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters +++ /dev/null @@ -1,441 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {0aa40751-a44a-400e-8809-ee817161e8e0} - - - {d70e7fca-2294-41a4-9cf8-78052bdb9aa4} - - - {01aed326-d2ec-457a-b99f-08ef32ed97fa} - - - {7ed2796a-da4b-4edd-8783-53e45d8d1c88} - - - {9ee086c2-1a95-48fb-92d8-4b7e7f6682ff} - - - {33813da8-81ac-449c-b19a-9756272519b9} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\TEdgeSegment - - - Header Files\TCollisionComponent - - - Header Files\TEdgeSegment - - - Header Files\TEdgeSegment - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files\TPinballComponent - - - Header Files\TCollisionComponent - - - Header Files\TCollisionComponent - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\TPinballComponent - - - Header Files - - - Header Files - - - Header Files\TPinballComponent - - - Header Files\TPinballComponent - - - Header Files\TEdgeSegment - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\TEdgeSegment - - - Source Files\TCollisionComponent - - - Source Files\TEdgeSegment - - - Source Files\TEdgeSegment - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files\TCollisionComponent - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\TPinballComponent - - - Source Files - - - Source Files - - - Source Files\TPinballComponent - - - Source Files\TPinballComponent - - - Source Files\TEdgeSegment - - - Source Files - - - Source Files - - - - - - - - Resource Files - - - - - Resource Files - - - - - Resource Files - - - Resource Files - - - \ No newline at end of file diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 7c3d660..367ef7a 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -443,25 +443,20 @@ int TPinballTable::Message(int code, float value) } BallCount = MaxBallCount; - Sound::Idle(); ChangeBallCount(BallCount); score::set(ScorePlayerNumber1, CurrentPlayer + 1); score::update(ScorePlayerNumber1); - Sound::Idle(); for (auto scoreIndex = 4 - PlayerCount; scoreIndex > 0; scoreIndex--) { score::set(PlayerScores[scoreIndex].ScoreStruct, -1); } - - Sound::Idle(); + ScoreSpecial3Flag = 0; ScoreSpecial2Flag = 0; UnknownP71 = 0; pinball::InfoTextBox->Clear(); - Sound::Idle(); pinball::MissTextBox->Clear(); - Sound::Idle(); LightGroup->Message(28, 0.2f); auto time = loader::play_sound(SoundIndex1); LightShowTimer = timer::set(time, this, LightShow_timeout); diff --git a/SpaceCadetPinball/WaveMix.cpp b/SpaceCadetPinball/WaveMix.cpp deleted file mode 100644 index e07524c..0000000 --- a/SpaceCadetPinball/WaveMix.cpp +++ /dev/null @@ -1,2627 +0,0 @@ -#include "pch.h" -#include "WaveMix.h" - -#include "pinball.h" - -int WaveMix::initialized_flag; -char WaveMix::FileName[276]; -CHANNELNODE WaveMix::channel_nodes[MAXQUEUEDWAVES]; -CHANNELNODE* WaveMix::free_channel_nodes; -unsigned char WaveMix::volume_table[11][256]; -int WaveMix::debug_flag; -void (*WaveMix::cmixit_ptr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume, int iNumWaves, - uint16_t length); -HMODULE WaveMix::HModule; -PCMWAVEFORMAT WaveMix::gpFormat = {{1u, 1u, 11025u, 11025u, 1u}, 8u}; -char WaveMix::string_buffer[256] = "WaveMix V 2.3 by Angel M. Diaz, Jr. (c) Microsoft 1993-1995"; -GLOBALS *WaveMix::Globals, *WaveMix::GlobalsActive; -int WaveMix::ShowDebugDialogs; -PLAYQUEUE WaveMix::play_queue; -CHANNELNODE* WaveMix::play_channel_array[MAXCHANNELS]; -XWAVEHDR* WaveMix::block_array1[10]; -XWAVEHDR* WaveMix::block_array2[10]; -unsigned char* WaveMix::play_data[MAXCHANNELS]; -volume_struct WaveMix::play_volume[MAXCHANNELS]; -int WaveMix::play_counter = 0; - -HANDLE WaveMix::Init() -{ - return ConfigureInit(nullptr); -} - -HANDLE WaveMix::ConfigureInit(MIXCONFIG* lpConfig) -{ - MIXCONFIG mixConfig{}; - - memset(&mixConfig, 0, sizeof(MIXCONFIG)); - unsigned int copySize = sizeof(MIXCONFIG); - mixConfig.RegistryKey = nullptr; - mixConfig.wSize = sizeof(MIXCONFIG); - if (lpConfig) - { - if (lpConfig->wSize < sizeof(MIXCONFIG)) - copySize = lpConfig->wSize; - memcpy(&mixConfig, lpConfig, copySize); - } - if (initialized_flag || Startup(GetModuleHandleA(nullptr)) != 0) - { - bool showDebugDialogs; - if ((mixConfig.dwFlags & 0x100) != 0) - showDebugDialogs = mixConfig.ShowDebugDialogs != 0; - else - showDebugDialogs = GetPrivateProfileIntA("general", "ShowDebugDialogs", 0, FileName) != 0; - ShowDebugDialogs = showDebugDialogs; - if (!waveOutGetNumDevs()) - { - if (ShowDebugDialogs) - { - wsprintfA(string_buffer, "This system does not have a valid wave output device."); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - } - return nullptr; - } - - if (GetPrivateProfileIntA("general", "ShowDevices", 0, FileName)) - ShowWaveOutDevices(); - auto globals = static_cast(LocalAlloc(LMEM_ZEROINIT, sizeof(GLOBALS))); - Globals = globals; - if (!globals) - return nullptr; - globals->CmixPtr = cmixit_ptr; - globals->wMagic2 = 21554; - globals->wMagic1 = 21554; - globals->WaveBlockArray = nullptr; - globals->SettingsDialogActiveFlag = 0; - globals->DefaultVolume.L = 10; - globals->DefaultVolume.R = 10; - memset(globals->aChannel, 0xFFu, sizeof globals->aChannel); - memmove(&globals->PCM, &gpFormat, sizeof(PCMWAVEFORMAT)); - if (!ReadConfigSettings(&mixConfig)) - { - Globals->wMagic2 = 0; - Globals->wMagic1 = 0; - LocalFree(Globals); - Globals = nullptr; - } - return Globals; - } - - return nullptr; -} - -int WaveMix::CloseSession(HANDLE hMixSession) -{ - Globals = SessionToGlobalDataPtr(hMixSession); - if (!Globals) - return 5; - - Activate(hMixSession, false); - CloseChannel(hMixSession, 0, 1); - memset(Globals, 0, sizeof(GLOBALS)); - Globals = nullptr; - if (!hMixSession || !LocalFree(hMixSession)) - return 5; - - return 0; -} - -int WaveMix::OpenChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags) -{ - GLOBALS* globals = SessionToGlobalDataPtr(hMixSession); - Globals = globals; - if (!globals) - return 5; - if (dwFlags > 2) - return 10; - if (dwFlags == 2 && (iChannel > 16 || iChannel < 1)) - return 11; - if (dwFlags == 0 && iChannel >= 16) - return 11; - - if (dwFlags) - { - if (dwFlags == 1) - iChannel = 16; - - for (auto index = iChannel - 1; index >= 0; --index) - { - if (globals->aChannel[index] == reinterpret_cast(-1)) - { - globals->aChannel[index] = nullptr; - globals->ChannelVolume[index].L = globals->DefaultVolume.L; - globals->ChannelVolume[index].R = globals->DefaultVolume.R; - ++globals->iChannels; - } - } - } - else - { - if (globals->aChannel[iChannel] != reinterpret_cast(-1)) - return 4; - globals->aChannel[iChannel] = nullptr; - globals->ChannelVolume[iChannel].L = globals->DefaultVolume.L; - globals->ChannelVolume[iChannel].R = globals->DefaultVolume.R; - ++globals->iChannels; - } - return 0; -} - -int WaveMix::CloseChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags) -{ - Globals = SessionToGlobalDataPtr(hMixSession); - if (!Globals) - return 5; - - int minChannel = iChannel, maxChannel; - int result = FlushChannel(hMixSession, iChannel, dwFlags | 2); - if (!result) - { - if ((dwFlags & 1) != 0) - { - minChannel = 0; - maxChannel = 16; - } - else - { - maxChannel = iChannel + 1; - if (iChannel >= maxChannel) - return 0; - } - - CHANNELNODE** channelPtr = &Globals->aChannel[minChannel]; - int index = maxChannel - minChannel; - do - { - if (*channelPtr != reinterpret_cast(-1)) - { - *channelPtr = reinterpret_cast(-1); - --Globals->iChannels; - } - ++channelPtr; - --index; - } - while (index); - return 0; - } - return result; -} - -int WaveMix::FlushChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags) -{ - int channelId; - int lastChannel; - - int remixFlag = 0; - auto globals = SessionToGlobalDataPtr(hMixSession); - Globals = globals; - if (!globals) - return 5; - - if ((dwFlags & 1) != 0) - { - channelId = 0; - lastChannel = 16; - } - else - { - channelId = iChannel; - if (iChannel < 0 || iChannel >= 16) - return 11; - if (globals->aChannel[iChannel] == reinterpret_cast(-1)) - return 5; - lastChannel = iChannel + 1; - if (iChannel >= lastChannel) - return 0; - } - - for (auto index = channelId; index < lastChannel; index++) - { - auto curChannel = globals->aChannel[index]; - if (curChannel != reinterpret_cast(-1)) - { - globals->aChannel[index] = nullptr; - remixFlag |= curChannel != nullptr; - while (curChannel) - { - auto tmp = curChannel->next; - FreeChannelNode(curChannel); - curChannel = tmp; - } - } - } - - if (remixFlag && (dwFlags & 2) == 0 && globals->fActive) - { - globals->pfnRemix(MyWaveOutGetPosition(globals->hWaveOut, globals->fGoodGetPos), nullptr); - } - return 0; -} - -MIXWAVE* WaveMix::OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned dwFlags) -{ - _MMIOINFO pmmioinfo; - _MMCKINFO pmmcki, pmmFmt; - HWAVEOUT phwo; - WAVEFORMATEX pwfx; - HMMIO hMmio = nullptr; - HGLOBAL hResData = nullptr; - HPSTR lpData = nullptr; - auto globals = SessionToGlobalDataPtr(hMixSession); - pwfx.wFormatTag = globals->PCM.wf.wFormatTag; - pwfx.nChannels = globals->PCM.wf.nChannels; - pwfx.nSamplesPerSec = globals->PCM.wf.nSamplesPerSec; - pwfx.nAvgBytesPerSec = globals->PCM.wf.nAvgBytesPerSec; - Globals = globals; - pwfx.nBlockAlign = globals->PCM.wf.nBlockAlign; - pwfx.wBitsPerSample = globals->PCM.wBitsPerSample; - pwfx.cbSize = 0; - if (waveOutOpen(&phwo, 0xFFFFFFFF, &pwfx, 0, 0, 1u)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "The waveform device can't play this format.", "WavMix32", MB_ICONWARNING); - return nullptr; - } - - auto mixWave = static_cast(GlobalLock(GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, sizeof(MIXWAVE)))); - if (!mixWave) - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONINFORMATION); - return nullptr; - } - - do - { - if ((dwFlags & 2) != 0) - { - HRSRC hrsc = FindResourceA(hInst, szWaveFilename, "WAVE"); - if (!hrsc || (hResData = LoadResource(hInst, hrsc)) == nullptr) - { - if (HIWORD(szWaveFilename)) - wsprintfA(string_buffer, "Failed to open 'WAVE' resource '%s'.", szWaveFilename); - else - wsprintfA(string_buffer, "Failed to open 'WAVE' resource %u.", LOWORD(szWaveFilename)); - if (ShowDebugDialogs) - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - break; - } - - memset(&pmmioinfo, 0, sizeof pmmioinfo); - pmmioinfo.pchBuffer = static_cast(LockResource(hResData)); - if (!pmmioinfo.pchBuffer) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to lock 'WAVE' resource", "WavMix32", MB_ICONWARNING); - FreeResource(hResData); - hResData = nullptr; - break; - } - - pmmioinfo.cchBuffer = SizeofResource(hInst, hrsc); - pmmioinfo.fccIOProc = FOURCC_MEM; - pmmioinfo.adwInfo[0] = 0; - hMmio = mmioOpenA(nullptr, &pmmioinfo, 0); - if (!hMmio) - { - if (ShowDebugDialogs) - { - wsprintfA(string_buffer, - "Failed to open resource, mmioOpen error=%u.\nMay need to make sure resource is marked read-write", - pmmioinfo.wErrorRet); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - } - break; - } - } - else if ((dwFlags & 4) != 0) - { - memcpy(&pmmioinfo, szWaveFilename, sizeof pmmioinfo); - hMmio = mmioOpenA(nullptr, &pmmioinfo, 0); - if (!hMmio) - { - if (ShowDebugDialogs) - { - wsprintfA(string_buffer, - "Failed to open memory file, mmioOpen error=%u.\nMay need to make sure memory is read-write", - pmmioinfo.wErrorRet); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - } - break; - } - } - else - { - hMmio = mmioOpenA(const_cast(szWaveFilename), nullptr, 0x10000u); - if (!hMmio) - { - if (ShowDebugDialogs) - { - wsprintfA(string_buffer, "Failed to open wave file %s.", szWaveFilename); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - } - break; - } - } - - pmmcki.fccType = mmioFOURCC('W', 'A', 'V', 'E'); - if (mmioDescend(hMmio, &pmmcki, nullptr, MMIO_FINDRIFF)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "This is not a WAVE file.", "WavMix32", MB_ICONWARNING); - break; - } - - pmmFmt.ckid = mmioFOURCC('f', 'm', 't', ' '); - if (mmioDescend(hMmio, &pmmFmt, &pmmcki, MMIO_FINDCHUNK)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "WAVE file is corrupted.", "WavMix32", MB_ICONWARNING); - break; - } - if (mmioRead(hMmio, (HPSTR)mixWave, 16) != 16) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to read format chunk.", "WavMix32", MB_ICONWARNING); - break; - } - if (mixWave->pcm.wf.wFormatTag != 1) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "The file is not a PCM file.", "WavMix32", MB_ICONWARNING); - break; - } - - mmioAscend(hMmio, &pmmFmt, 0); - pmmFmt.ckid = mmioFOURCC('d', 'a', 't', 'a'); - if (mmioDescend(hMmio, &pmmFmt, &pmmcki, MMIO_FINDCHUNK)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "WAVE file has no data chunk.", "WavMix32", MB_ICONWARNING); - break; - } - auto dataSize = pmmFmt.cksize; - if (!pmmFmt.cksize) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "The data chunk has no data.", "WavMix32", MB_ICONWARNING); - break; - } - - lpData = static_cast(GlobalLock(GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, pmmFmt.cksize))); - if (!lpData) - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONINFORMATION); - break; - } - - auto readCount = mmioRead(hMmio, lpData, dataSize); - if (readCount != static_cast(dataSize)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to read data chunk.", "WavMix32", MB_ICONWARNING); - break; - } - lpData = WaveFormatConvert(&Globals->PCM, &mixWave->pcm, lpData, &dataSize); - if (!lpData) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to convert wave format.", "WavMix32", MB_ICONWARNING); - break; - } - mmioClose(hMmio, 0); - if (hResData) - FreeResource(hResData); - mixWave->wh.dwBufferLength = dataSize; - mixWave->wh.lpData = lpData; - mixWave->wh.dwFlags = 0; - mixWave->wh.dwLoops = 0; - mixWave->wh.dwUser = 0; - mixWave->wMagic = 21554; - memmove(&mixWave->pcm, &Globals->PCM, sizeof(PCMWAVEFORMAT)); - - if (HIWORD(szWaveFilename)) - { - auto fileNameLength = lstrlenA(szWaveFilename); - int copyOffset = fileNameLength > 15 ? fileNameLength - 15 : 0; - lstrcpyA(mixWave->szWaveFilename, &szWaveFilename[copyOffset]); - } - else - { - wsprintfA(mixWave->szWaveFilename, "res#%u", LOWORD(szWaveFilename)); - } - return mixWave; - } - while (false); - - if (hMmio) - mmioClose(hMmio, 0); - GlobalUnlock(GlobalHandle(mixWave)); - GlobalFree(GlobalHandle(mixWave)); - if (lpData) - { - GlobalUnlock(GlobalHandle(lpData)); - GlobalFree(GlobalHandle(lpData)); - } - if (hResData) - FreeResource(hResData); - return nullptr; -} - -int WaveMix::FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave) -{ - GLOBALS* globals = SessionToGlobalDataPtr(hMixSession); - if (!globals) - return 5; - if (!IsValidLPMIXWAVE(lpMixWave)) - return 5; - - CHANNELNODE** channelPtr = globals->aChannel; - for (auto index = 16; index; --index) - { - CHANNELNODE* channel = *channelPtr; - if (channel != reinterpret_cast(-1)) - { - CHANNELNODE* prevChannel = nullptr; - while (channel) - { - if (channel->lpMixWave == lpMixWave) - { - if (prevChannel) - { - prevChannel->next = channel->next; - FreeChannelNode(channel); - channel = prevChannel->next; - } - else - { - channel = channel->next; - FreeChannelNode(channel); - *channelPtr = channel; - } - } - else - { - prevChannel = channel; - channel = channel->next; - } - } - } - ++channelPtr; - } - - if (lpMixWave->wh.lpData) - { - GlobalUnlock(GlobalHandle(lpMixWave->wh.lpData)); - GlobalFree(GlobalHandle(lpMixWave->wh.lpData)); - } - lpMixWave->wMagic = 0; - GlobalUnlock(GlobalHandle(lpMixWave)); - GlobalFree(GlobalHandle(lpMixWave)); - return 0; -} - -int WaveMix::Activate(HANDLE hMixSession, bool fActivate) -{ - GLOBALS* globals = SessionToGlobalDataPtr(hMixSession); - Globals = globals; - if (!globals) - return 5; - if (fActivate) - { - if (GlobalsActive) - return GlobalsActive != globals ? 4 : 0; - if (globals->SettingsDialogActiveFlag) - return 12; - GlobalsActive = globals; - sndPlaySoundA(nullptr, 0); - auto result = GetWaveDevice(); - if (result) - { - GlobalsActive = nullptr; - return result; - } - Globals->fActive = 1; - SetWaveOutPosition(Globals->dwCurrentSample); - XWAVEHDR* xHDR; - do - xHDR = GetWaveBlock(); - while (MixerPlay(xHDR, 1)); - } - else - { - if (globals->fActive) - { - Globals->dwCurrentSample = MyWaveOutGetPosition(globals->hWaveOut, globals->fGoodGetPos); - } - ReleaseWaveDevice(globals); - Globals->fActive = 0; - if (Globals == GlobalsActive) - GlobalsActive = nullptr; - } - return 0; -} - -void WaveMix::Pump() -{ - Globals = GlobalsActive; - if (GlobalsActive) - { - auto xHDR = play_queue.first; - while (xHDR) - { - if ((xHDR->wh.dwFlags & 1) != 0) - { - RemoveFromPlayingQueue(xHDR); - xHDR->fAvailable = 1; - xHDR = play_queue.first; - } - else - xHDR = xHDR->QNext; - } - FreePlayedBlocks(); - while (MixerPlay(GetWaveBlock(), 1)); - } -} - -int WaveMix::Play(MIXPLAYPARAMS* lpMixPlayParams) -{ - ++play_counter; - auto result = 12; - auto remixFlag = 0; - - do - { - if (play_counter > 1) - break; - - if (!lpMixPlayParams) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "NULL parameters pointer passed to WaveMixPlay!", "WavMix32", MB_ICONWARNING); - result = 5; - break; - } - - auto globals = SessionToGlobalDataPtr(lpMixPlayParams->hMixSession); - Globals = globals; - if (!globals) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Invalid session handle passed to WaveMixPlay", "WavMix32", MB_ICONWARNING); - result = 5; - break; - } - - if (!IsValidLPMIXWAVE(lpMixPlayParams->lpMixWave)) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Invalid or NULL wave pointer passed to WaveMixPlay!", "WavMix32", MB_ICONWARNING); - break; - } - - if (!HasCurrentOutputFormat(lpMixPlayParams->lpMixWave)) - { - wsprintfA( - string_buffer, - "The LPMIXWAVE 0x%lx is not in the current output format, close the wave and reopen it.", - lpMixPlayParams->lpMixWave); - if (ShowDebugDialogs) - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - result = 8; - break; - } - if (!globals->fActive) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Wave device not allocated, call WaveMixActivate(hMixSession,TRUE)", "WavMix32", - MB_ICONWARNING); - result = 4; - break; - } - if (!globals->iChannels) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "You must open a channel before you can play a wave!", "WavMix32", MB_ICONWARNING); - result = 5; - break; - } - - int iChannel; - if ((lpMixPlayParams->dwFlags & WMIX_USELRUCHANNEL) != 0) - { - iChannel = 0; - for (auto channelIndex = 0; channelIndex < 16; ++channelIndex) - { - if (globals->aChannel[channelIndex] != reinterpret_cast(-1)) - { - if (!globals->aChannel[iChannel]) - break; - if (channelIndex != iChannel && globals->MRUChannel[channelIndex] < globals->MRUChannel[iChannel]) - iChannel = channelIndex; - } - } - lpMixPlayParams->iChannel = iChannel; - } - else - { - iChannel = lpMixPlayParams->iChannel; - } - ++globals->dwMRU; - globals->MRUChannel[iChannel] = globals->dwMRU; - if (globals->aChannel[iChannel] == reinterpret_cast(-1)) - { - result = 5; - break; - } - - auto channel = GetChannelNode(); - if (!channel) - break; - - memcpy(&channel->PlayParams, lpMixPlayParams, sizeof channel->PlayParams); - channel->lpMixWave = channel->PlayParams.lpMixWave; - channel->dwNumSamples = channel->PlayParams.lpMixWave->wh.dwBufferLength; - auto lpData = (uint8_t*)channel->PlayParams.lpMixWave->wh.lpData; - channel->lpPos = lpData; - channel->lpEnd = &lpData[channel->dwNumSamples - globals->PCM.wf.nBlockAlign]; - channel->PlayParams.iChannel = iChannel; - if (globals->pWaitList) - { - channel->next = globals->pWaitList->next; - globals->pWaitList->next = channel; - globals->pWaitList = channel; - } - else - { - globals->pWaitList = channel; - channel->next = channel; - } - - if ((channel->PlayParams.dwFlags & WMIX_WAIT) != 0) - { - result = 0; - break; - } - - ResetWavePosIfNoChannelData(); - auto globals2 = Globals; - unsigned wavePosition; - if (Globals->pfnRemix == ResetRemix) - { - wavePosition = MyWaveOutGetPosition(Globals->hWaveOut, Globals->fGoodGetPos); - globals2 = Globals; - } - else - { - wavePosition = Globals->dwCurrentSample; - } - - while (globals2->pWaitList) - { - auto curChannel = globals2->pWaitList->next; - if (globals2->pWaitList->next == globals2->pWaitList) - globals2->pWaitList = nullptr; - else - globals2->pWaitList->next = curChannel->next; - - iChannel = curChannel->PlayParams.iChannel; - curChannel->next = nullptr; - if ((curChannel->PlayParams.dwFlags & WMIX_CustomVolume) != 0) - { - curChannel->Volume.L = curChannel->PlayParams.Volume.L; - curChannel->Volume.R = curChannel->PlayParams.Volume.R; - } - else - { - curChannel->Volume.L = globals2->ChannelVolume[iChannel].L; - curChannel->Volume.R = globals2->ChannelVolume[iChannel].R; - } - if (curChannel->Volume.L > 10u) - curChannel->Volume.L = 10; - if (curChannel->Volume.R > 10u) - curChannel->Volume.R = 10; - - if ((curChannel->PlayParams.dwFlags & WMIX_CLEARQUEUE) != 0) - { - for (auto tmpCh = globals2->aChannel[iChannel]; tmpCh;) - { - auto nextChannel = tmpCh->next; - FreeChannelNode(tmpCh); - tmpCh = nextChannel; - } - globals2->aChannel[iChannel] = curChannel; - if (play_queue.first != nullptr) - remixFlag = 1; - if ((curChannel->PlayParams.dwFlags & WMIX_HIPRIORITY) != 0) - curChannel->dwStartPos = wavePosition; - else - curChannel->dwStartPos = globals2->dwCurrentSample; - } - else - { - DWORD dwStartPos; - if (globals2->aChannel[iChannel]) - { - auto tmpCh = globals2->aChannel[iChannel]; - while (tmpCh->next) - tmpCh = tmpCh->next; - tmpCh->next = curChannel; - dwStartPos = tmpCh->dwEndPos; - - if ((curChannel->PlayParams.dwFlags & WMIX_HIPRIORITY) != 0) - { - if (dwStartPos <= wavePosition) - dwStartPos = wavePosition; - } - else if (globals2->dwCurrentSample > dwStartPos) - { - dwStartPos = globals2->dwCurrentSample; - } - } - else - { - dwStartPos = wavePosition; - globals2->aChannel[iChannel] = curChannel; - if ((curChannel->PlayParams.dwFlags & WMIX_HIPRIORITY) == 0) - dwStartPos = globals2->dwCurrentSample; - } - curChannel->dwStartPos = dwStartPos; - if (globals2->dwCurrentSample > curChannel->dwStartPos) - remixFlag = 1; - } - if (curChannel->PlayParams.wLoops == 0xFFFF) - curChannel->dwEndPos = -1; - else - curChannel->dwEndPos = curChannel->dwStartPos + curChannel->dwNumSamples * (curChannel->PlayParams. - wLoops + 1) - globals2->PCM.wf.nBlockAlign; - } - - if (!remixFlag || !globals2->pfnRemix(wavePosition, nullptr)) - { - int pauseFlag; - if (play_queue.first || globals2->PauseBlocks <= 0) - { - pauseFlag = 0; - } - else - { - waveOutPause(globals2->hWaveOut); - pauseFlag = 1; - } - - auto pauseCounter = 0; - while (MixerPlay(GetWaveBlock(), 1)) - { - if (pauseFlag) - { - if (++pauseCounter >= Globals->PauseBlocks) - { - waveOutRestart(Globals->hWaveOut); - pauseFlag = 0; - } - } - } - if (pauseFlag) - waveOutRestart(Globals->hWaveOut); - } - - result = 0; - } - while (false); - - --play_counter; - return result; -} - -GLOBALS* WaveMix::SessionToGlobalDataPtr(HANDLE hMixSession) -{ - auto globals = static_cast(hMixSession); - if (hMixSession && globals->wMagic1 == 21554 && globals->wMagic2 == 21554) - return globals; - MessageBeep(0xFFFFFFFF); - wsprintfA(string_buffer, "Invalid session handle 0x%04X passed to WaveMix API", hMixSession); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONWARNING); - return nullptr; -} - -int WaveMix::Startup(HMODULE hModule) -{ - WNDCLASSA WndClass; - - if (initialized_flag) - return 1; - if (!SetIniFileName(hModule)) - return 0; - InitVolumeTable(); - debug_flag = GetPrivateProfileIntA("general", "debug", 0, FileName); - cmixit_ptr = cmixit; - HModule = hModule; - - WndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW); - WndClass.hIcon = nullptr; - WndClass.lpszMenuName = nullptr; - WndClass.lpszClassName = "WavMix32"; - WndClass.hbrBackground = static_cast(GetStockObject(1)); - WndClass.hInstance = HModule; - WndClass.style = 0; - WndClass.lpfnWndProc = WndProc; - WndClass.cbWndExtra = 0; - WndClass.cbClsExtra = 0; - if (!RegisterClassA(&WndClass)) - return 0; - InitChannelNodes(); - initialized_flag = 1; - return 1; -} - -int WaveMix::SetIniFileName(HMODULE hModule) -{ - int result = GetModuleFileNameA(hModule, FileName, 0x104u); - if (result) - { - char* i; - for (i = &FileName[result]; *i != '\\'; --i) - { - } - *i = 0; - lstrcpyA(i, "\\WAVEMIX.INF"); - result = 1; - } - return result; -} - -void WaveMix::InitChannelNodes() -{ - CHANNELNODE* channelPtr = channel_nodes; - do - { - channelPtr->next = channelPtr + 1; - ++channelPtr; - } - while (channelPtr < &channel_nodes[MAXQUEUEDWAVES - 2]); - channel_nodes[MAXQUEUEDWAVES - 1].next = nullptr; - free_channel_nodes = channel_nodes; -} - -void WaveMix::InitVolumeTable() -{ - int index3Sub = 0; - for (auto volume = 0; volume < 11; volume++) - { - auto tablePtr = &volume_table[volume][0]; - for (auto divSmth = index3Sub, sample = 0; sample < 256; ++sample) - { - tablePtr[sample] = static_cast(divSmth / 10 + 128); - divSmth += volume; - } - index3Sub -= 128; - } -} - -void WaveMix::ShowWaveOutDevices() -{ - tagWAVEOUTCAPSA pwoc{}; - - auto deviceCount = waveOutGetNumDevs(); - if (deviceCount) - { - wsprintfA(string_buffer, "%d waveOut Devices have been detected on your system.", deviceCount); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - for (auto uDeviceID = 0u; uDeviceID < deviceCount; ++uDeviceID) - { - if (!waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u) && RemoveInvalidIniNameCharacters(pwoc.szPname)) - wsprintfA( - string_buffer, - "Device %i: %s\n\tVersion %u.%u", - uDeviceID, - pwoc.szPname, - HIBYTE(pwoc.vDriverVersion), - LOBYTE(pwoc.vDriverVersion)); - else - wsprintfA(string_buffer, "waveOutGetDevCaps failed (err %u) for device %d", 1, uDeviceID); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - } - } -} - -int WaveMix::RemoveInvalidIniNameCharacters(char* lpString) -{ - auto stringPtr = lpString; - if (!lpString || !*lpString) - return 0; - do - { - if (!isalnum(*stringPtr) && !isspace(*stringPtr)) - break; - ++stringPtr; - } - while (*stringPtr); - - do - *stringPtr-- = 0; - while (stringPtr >= lpString && isspace(*stringPtr)); - return lstrlenA(lpString); -} - -int WaveMix::ReadConfigSettings(MIXCONFIG* lpConfig) -{ - auto waveDeviceCount = waveOutGetNumDevs(); - if (!waveDeviceCount) - return 0; - if ((lpConfig->dwFlags & 0x400) != 0 && ReadRegistryForAppSpecificConfigs(lpConfig)) - { - Configure(Globals, nullptr, lpConfig, nullptr, 0); - return 1; - } - - UINT deviceId; - if (static_cast(lpConfig->dwFlags) >= 0) - { - deviceId = GetPrivateProfileIntA("general", "WaveOutDevice", 0, FileName); - } - else - { - deviceId = lpConfig->wDeviceID; - } - Globals->wDeviceID = deviceId; - if (Globals->wDeviceID >= waveDeviceCount) - Globals->wDeviceID = 0; - - if (waveOutGetDevCapsA(Globals->wDeviceID, &Globals->WaveoutCaps, 0x34u) - || !RemoveInvalidIniNameCharacters(Globals->WaveoutCaps.szPname)) - { - lstrcpyA(Globals->WaveoutCaps.szPname, "Unkown Device"); - } - - if (!ReadRegistryToGetMachineSpecificInfSection(Globals->wDeviceID, Globals->szDevicePName, 96)) - { - lstrcpyA(Globals->szDevicePName, GetOperatingSystemPrefix()); - lstrcatA(Globals->szDevicePName, Globals->WaveoutCaps.szPname); - } - - auto remix = GetPrivateProfileIntA("default", "Remix", 1, FileName); - auto goodWavePos = GetPrivateProfileIntA("default", "GoodWavePos", DefaultGoodWavePos(Globals->wDeviceID), - FileName); - auto waveBlocks = GetPrivateProfileIntA("default", "WaveBlocks", 3, FileName); - auto samplesPerSec = GetPrivateProfileIntA("default", "SamplesPerSec", 11, FileName); - if ((Globals->WaveoutCaps.dwSupport & 0x10) != 0) - { - if (!ShowDebugDialogs) - return 0; - wsprintfA(string_buffer, - "%s is a syncronous (blocking) wave output device. This will not permit audio to play while other applications are running.", - Globals->WaveoutCaps.szPname); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - return 0; - } - if (GetPrivateProfileIntA("not compatible", Globals->szDevicePName, 0, FileName)) - { - if (!ShowDebugDialogs) - return 0; - wsprintfA(string_buffer, "%s is not compatible with the realtime wavemixer.", Globals->szDevicePName); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - return 0; - } - - Globals->pfnRemix = GetPrivateProfileIntA(Globals->szDevicePName, "Remix", remix, FileName) != 2 - ? ResetRemix - : NoResetRemix; - Globals->fGoodGetPos = GetPrivateProfileIntA(Globals->szDevicePName, "GoodWavePos", goodWavePos, FileName) != 0; - Globals->WaveBlockCount = GetPrivateProfileIntA(Globals->szDevicePName, "WaveBlocks", waveBlocks, FileName); - if (Globals->WaveBlockCount < 2) - Globals->WaveBlockCount = 2; - else if (Globals->WaveBlockCount > 10) - Globals->WaveBlockCount = 10; - - Globals->PauseBlocks = GetPrivateProfileIntA(Globals->szDevicePName, "PauseBlocks", - DefaultPauseBlocks(Globals->WaveBlockCount), FileName); - if (Globals->PauseBlocks >= 0) - { - if (Globals->PauseBlocks > Globals->WaveBlockCount) - Globals->PauseBlocks = Globals->WaveBlockCount; - } - else - { - Globals->PauseBlocks = 0; - } - - auto samplesPerSec2 = GetPrivateProfileIntA(Globals->szDevicePName, "SamplesPerSec", samplesPerSec, FileName); - auto channels = GetPrivateProfileIntA(Globals->szDevicePName, "Channels", 1, FileName); - Globals->PCM.wf.nChannels = channels; - if (channels) - { - if (channels > 2u) - Globals->PCM.wf.nChannels = 2; - } - else - { - Globals->PCM.wf.nChannels = 1; - } - DWORD nAvgBytesPerSec; - if (samplesPerSec2 == 22) - { - Globals->PCM.wf.nSamplesPerSec = 22050; - nAvgBytesPerSec = 22050 * Globals->PCM.wf.nChannels; - } - else if (samplesPerSec2 == 44) - { - Globals->PCM.wf.nSamplesPerSec = 44100; - nAvgBytesPerSec = 44100 * Globals->PCM.wf.nChannels; - } - else - { - nAvgBytesPerSec = 11025 * Globals->PCM.wf.nChannels; - } - Globals->PCM.wf.nAvgBytesPerSec = nAvgBytesPerSec; - auto waveBlockLen2 = GetPrivateProfileIntA("default", "WaveBlockLen", 0, FileName); - Globals->dwWaveBlockLen = FigureOutDMABufferSize(waveBlockLen2, &Globals->PCM); - Configure(Globals, nullptr, lpConfig, nullptr, 0); - return 1; -} - -int WaveMix::ReadRegistryForAppSpecificConfigs(MIXCONFIG* lpConfig) -{ - HKEY phkResult; - CHAR SubKey[52]; - - DWORD dwFlags = lpConfig->dwFlags; - if ((dwFlags & 0x400) == 0 || !lpConfig->RegistryKey) - return 0; - if ((dwFlags & 0x80u) == 0) - { - lpConfig->wDeviceID = Globals->wDeviceID; - } - else if (lpConfig->wDeviceID >= waveOutGetNumDevs()) - { - lpConfig->wDeviceID = 0; - } - wsprintfA(SubKey, "WaveMix\\Device%u", lpConfig->wDeviceID); - if (RegOpenKeyA(lpConfig->RegistryKey, SubKey, &phkResult)) - return 0; - if ((dwFlags & 1) == 0) - lpConfig->wChannels = ReadRegistryInt(phkResult, "Channels", 1); - if ((dwFlags & 2) == 0) - lpConfig->wSamplingRate = ReadRegistryInt(phkResult, "SamplesPerSec", 11); - if ((dwFlags & 4) == 0) - lpConfig->WaveBlockCount = static_cast(ReadRegistryInt(phkResult, "WaveBlocks", 3)); - if ((dwFlags & 8) == 0) - lpConfig->WaveBlockLen = static_cast(ReadRegistryInt(phkResult, "WaveBlockLen", 0)); - lpConfig->CmixPtrDefaultFlag = 1; - if ((dwFlags & 0x20) == 0) - lpConfig->ResetMixDefaultFlag = static_cast(ReadRegistryInt(phkResult, "Remix", 1)) != 2; - if ((dwFlags & 0x40) == 0) - { - int defaultGoodWavePos = DefaultGoodWavePos(lpConfig->wDeviceID); - lpConfig->GoodWavePos = static_cast(ReadRegistryInt( - phkResult, "GoodWavePos", defaultGoodWavePos)) != 0; - } - if ((dwFlags & 0x100) == 0) - lpConfig->ShowDebugDialogs = static_cast(ReadRegistryInt(phkResult, "ShowDebugDialogs", 0)); - if ((dwFlags & 0x200) == 0) - { - int defaultPauseBlocks = DefaultPauseBlocks(static_cast(lpConfig->WaveBlockCount)); - lpConfig->PauseBlocks = static_cast(ReadRegistryInt(phkResult, "PauseBlocks", defaultPauseBlocks)); - } - lpConfig->dwFlags = 1023; - waveOutGetDevCapsA(lpConfig->wDeviceID, &Globals->WaveoutCaps, 0x34u); - RegCloseKey(phkResult); - return 1; -} - -int WaveMix::ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int defaultValue) -{ - int result; - LONG cbData = 10; - char Data[12]; - - if (!hKey || RegQueryValueA(hKey, lpSubKey, Data, &cbData)) - result = defaultValue; - else - result = atol(Data); - return result; -} - -int WaveMix::DefaultGoodWavePos(unsigned uDeviceID) -{ - int result; - struct tagWAVEOUTCAPSA pwoc{}; - - auto deviceCount = waveOutGetNumDevs(); - if (uDeviceID > deviceCount || (uDeviceID & 0x80000000) != 0 || - !deviceCount || waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u)) - { - result = 0; - } - else - { - result = LOBYTE(pwoc.dwSupport) >> 5 & 1; - } - return result; -} - -#pragma warning (disable : 4996)/*Original uses GetVersion*/ -int WaveMix::DefaultPauseBlocks(int waveBlocks) -{ - int result; - if (GetVersion() < 0x80000000 || static_cast(GetVersion()) < 4u) - result = waveBlocks; - else - result = 0; - return result; -} -#pragma warning (default : 4996) - -int WaveMix::Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag) -{ - MIXCONFIG mixConfigLocal{}; - tagWAVEOUTCAPSA pwoc{}; - - auto mixConfig = lpConfig; - auto someFlag1 = 0; - auto globals = SessionToGlobalDataPtr(hMixSession); - Globals = globals; - if (!globals) - return 5; - if (globals->fActive) - return 4; - if (globals->SettingsDialogActiveFlag) - return 12; - FlushChannel(hMixSession, -1, 1u); - - if (!mixConfig) - { - mixConfigLocal.wSize = sizeof(MIXCONFIG); - mixConfigLocal.dwFlags = 1023; - GetConfig(static_cast(hMixSession), &mixConfigLocal); - auto dialog = MakeSettingsDlgTemplate(); - if (!dialog) - return 1; - Globals->SettingsDialogActiveFlag = 1; - auto dlgResult = DialogBoxIndirectParamA(HModule, &dialog->Dialog, hWndParent, SettingsDlgProc, - (LPARAM)&mixConfigLocal); - DestroySettingsDlgTemplate(dialog); - Globals->SettingsDialogActiveFlag = 0; - if (dlgResult != 1) - return 1; - if (Globals->dwWaveBlockLen == mixConfigLocal.WaveBlockLen) - mixConfigLocal.dwFlags &= 0xFFFFFFF7; - - mixConfig = &mixConfigLocal; - } - if (!mixConfig->dwFlags) - return 1; - - globals = SessionToGlobalDataPtr(hMixSession); - Globals = globals; - if (!globals) - return 5; - - auto dwFlags = mixConfig->dwFlags; - if ((dwFlags & 0x100) != 0) - ShowDebugDialogs = mixConfig->ShowDebugDialogs != 0; - if ((dwFlags & 0x80u) != 0) - { - if (mixConfig->wDeviceID != globals->wDeviceID) - { - auto result = waveOutGetDevCapsA(mixConfig->wDeviceID, &pwoc, 0x34u); - if (result) - return result; - memcpy(&Globals->WaveoutCaps, &pwoc, sizeof Globals->WaveoutCaps); - Globals->wDeviceID = mixConfig->wDeviceID; - if (Globals->WaveoutCaps.wChannels == 1 && Globals->PCM.wf.nChannels == 2) - { - Globals->PCM.wf.nChannels = 1; - someFlag1 = 1; - Globals->PCM.wf.nBlockAlign = 1; - Globals->PCM.wf.nAvgBytesPerSec = Globals->PCM.wf.nSamplesPerSec; - } - lstrcpyA(globals->szDevicePName, pwoc.szPname); - if (!RemoveInvalidIniNameCharacters(Globals->szDevicePName)) - lstrcpyA(Globals->szDevicePName, "Unkown Device"); - if (!ReadRegistryToGetMachineSpecificInfSection(Globals->wDeviceID, Globals->szDevicePName, 96)) - { - lstrcpyA(Globals->szDevicePName, GetOperatingSystemPrefix()); - lstrcatA(Globals->szDevicePName, Globals->WaveoutCaps.szPname); - } - } - } - - if ((dwFlags & 1) != 0) - { - if (mixConfig->wChannels <= 1u) - { - if (globals->PCM.wf.nChannels == 2) - someFlag1 = 1; - globals->PCM.wf.nChannels = 1; - globals->PCM.wf.nBlockAlign = 1; - globals->PCM.wf.nAvgBytesPerSec = globals->PCM.wf.nSamplesPerSec; - } - if (globals->WaveoutCaps.wChannels > 1u) - { - if (globals->PCM.wf.nChannels == 1) - someFlag1 = 1; - globals->PCM.wf.nChannels = 2; - globals->PCM.wf.nBlockAlign = 2; - globals->PCM.wf.nAvgBytesPerSec = 2 * globals->PCM.wf.nSamplesPerSec; - } - } - - if ((dwFlags & 2) != 0) - { - auto nAvgBytesPerSec = 0u; - if (mixConfig->wSamplingRate == 22) - { - if (globals->PCM.wf.nSamplesPerSec != 22050) - someFlag1 = 1; - globals->PCM.wf.nSamplesPerSec = 22050; - nAvgBytesPerSec = 22050 * globals->PCM.wf.nChannels; - } - else - { - if (mixConfig->wSamplingRate == 44) - { - if (globals->PCM.wf.nSamplesPerSec != 44100) - someFlag1 = 1; - globals->PCM.wf.nSamplesPerSec = 44100; - nAvgBytesPerSec = 44100 * globals->PCM.wf.nChannels; - } - else - { - if (globals->PCM.wf.nSamplesPerSec != 11025) - someFlag1 = 1; - globals->PCM.wf.nSamplesPerSec = 11025; - nAvgBytesPerSec = 11025 * globals->PCM.wf.nChannels; - } - } - globals->PCM.wf.nAvgBytesPerSec = nAvgBytesPerSec; - } - - if ((dwFlags & 4) != 0) - { - auto v24 = 2; - globals->WaveBlockCount = mixConfig->WaveBlockCount; - if (mixConfig->WaveBlockCount < 2) - globals->WaveBlockCount = 2; - else if (mixConfig->WaveBlockCount > 10) - globals->WaveBlockCount = 10; - if (globals->PauseBlocks >= 0) - { - if (globals->PauseBlocks > globals->WaveBlockCount) - globals->PauseBlocks = globals->WaveBlockCount; - } - else - { - globals->PauseBlocks = 0; - } - } - - if (someFlag1) - globals->dwWaveBlockLen = FigureOutDMABufferSize(0, &globals->PCM); - - if ((dwFlags & 8) != 0) - { - if (mixConfig->WaveBlockLen) - globals->dwWaveBlockLen = mixConfig->WaveBlockLen; - } - - if (globals->dwWaveBlockLen < 344) - globals->dwWaveBlockLen = 344; - else if (globals->dwWaveBlockLen > 11025) - globals->dwWaveBlockLen = 11025; - - auto dwFlags2 = dwFlags; - if ((dwFlags & 0x10) != 0) - globals->CmixPtr = cmixit; - - if ((dwFlags2 & 0x20) != 0) - { - globals->pfnRemix = !mixConfig->ResetMixDefaultFlag ? NoResetRemix : ResetRemix; - } - - if ((dwFlags2 & 0x40) != 0) - globals->fGoodGetPos = mixConfig->GoodWavePos != 0; - - if ((dwFlags2 & 0x200) != 0) - { - globals->PauseBlocks = mixConfig->PauseBlocks; - if (mixConfig->PauseBlocks > globals->WaveBlockCount) - globals->PauseBlocks = globals->WaveBlockCount; - } - - GetConfig(hMixSession, mixConfig); - if (flag1Ptr) - *flag1Ptr = someFlag1; - if (saveConfigFlag) - SaveConfigSettings(dwFlags); - if (ShowDebugDialogs) - ShowCurrentSettings(); - return 0; -} - -int WaveMix::GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig) -{ - GLOBALS* globals = SessionToGlobalDataPtr(static_cast(hMixSession)); - Globals = globals; - if (!globals) - return 5; - if (!lpConfig) - return 11; - - DWORD dwFlags = lpConfig->dwFlags; - if ((dwFlags & 1) != 0) - lpConfig->wChannels = globals->PCM.wf.nChannels; - if ((dwFlags & 2) != 0) - lpConfig->wSamplingRate = static_cast(11 * (globals->PCM.wf.nSamplesPerSec / 0x2B11)); - if ((dwFlags & 4) != 0) - lpConfig->WaveBlockCount = globals->WaveBlockCount; - if ((dwFlags & 8) != 0) - lpConfig->WaveBlockLen = static_cast(globals->dwWaveBlockLen); - if ((dwFlags & 0x10) != 0) - lpConfig->CmixPtrDefaultFlag = globals->CmixPtr == cmixit; - if ((dwFlags & 0x20) != 0) - lpConfig->ResetMixDefaultFlag = globals->pfnRemix == ResetRemix; - if ((dwFlags & 0x40) != 0) - lpConfig->GoodWavePos = globals->fGoodGetPos; - if ((dwFlags & 0x80u) != 0) - lpConfig->wDeviceID = globals->wDeviceID; - if ((dwFlags & 0x100) != 0) - lpConfig->ShowDebugDialogs = ShowDebugDialogs != 0; - if ((dwFlags & 0x200) != 0) - lpConfig->PauseBlocks = globals->PauseBlocks; - return 0; -} - -unsigned WaveMix::MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos) -{ - mmtime_tag pmmt{}; - - if (!fGoodGetPos) - return (timeGetTime() - Globals->dwBaseTime) * Globals->PCM.wf.nAvgBytesPerSec / 0x3E8 & 0xFFFFFFF8; - pmmt.wType = TIME_BYTES; - waveOutGetPosition(hWaveOut, &pmmt, 0xCu); - return Globals->pfnSampleAdjust(pmmt.u.ms, Globals->dwWaveOutPos); -} - -void WaveMix::FreeChannelNode(CHANNELNODE* channel) -{ - if (channel) - { - channel->next = free_channel_nodes; - free_channel_nodes = channel; - } -} - -int WaveMix::ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel) -{ - Globals->dwCurrentSample = dwRemixSamplePos; - DestroyPlayQueue(); - SwapWaveBlocks(); - - while (true) - { - auto block = GetWaveBlock(); - if (!block) - break; - if (!MixerPlay(block, 0)) - { - block->fAvailable = 1; - break; - } - AddToPlayingQueue(block); - } - - auto dwCurrentSamplePrev = Globals->dwCurrentSample; - MyWaveOutReset(Globals->hWaveOut); - Globals->dwCurrentSample = dwCurrentSamplePrev; - auto pauseFlag = 0; - if (Globals->PauseBlocks > 0) - { - waveOutPause(Globals->hWaveOut); - pauseFlag = 1; - } - - auto pauseCount = 0; - for (auto xHDR = play_queue.first; xHDR; xHDR = xHDR->QNext) - { - if (waveOutWrite(Globals->hWaveOut, &xHDR->wh, sizeof(WAVEHDR))) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to write block to device", "WavMix32", MB_ICONWARNING); - xHDR->fAvailable = 1; - RemoveFromPlayingQueue(xHDR); - } - if (pauseFlag) - { - if (++pauseCount >= Globals->PauseBlocks) - { - waveOutRestart(Globals->hWaveOut); - pauseFlag = 0; - } - } - } - if (pauseFlag) - waveOutRestart(Globals->hWaveOut); - return 1; -} - -XWAVEHDR* WaveMix::RemoveFromPlayingQueue(XWAVEHDR* lpXWH) -{ - if (!play_queue.first) - return nullptr; - - if (lpXWH != play_queue.first) - { - XWAVEHDR* prev = play_queue.first; - XWAVEHDR* current = play_queue.first->QNext; - while (current) - { - if (current == lpXWH) - break; - prev = current; - current = current->QNext; - } - if (!current) - return nullptr; - - prev->QNext = current->QNext; - if (current == play_queue.last) - play_queue.last = prev; - } - else - { - play_queue.first = lpXWH->QNext; - if (!play_queue.first) - play_queue.last = nullptr; - } - - lpXWH->QNext = nullptr; - return lpXWH; -} - -void WaveMix::DestroyPlayQueue() -{ - while (play_queue.first) - { - play_queue.first->fAvailable = 1; - RemoveFromPlayingQueue(play_queue.first); - } -} - -void WaveMix::SwapWaveBlocks() -{ - if (Globals->WaveBlockArray == block_array1) - Globals->WaveBlockArray = block_array2; - else - Globals->WaveBlockArray = block_array1; -} - -XWAVEHDR* WaveMix::GetWaveBlock() -{ - int index = 0; - for (; index < Globals->WaveBlockCount; index++) - if (Globals->WaveBlockArray[index]->fAvailable) - break; - if (index >= Globals->WaveBlockCount) - return nullptr; - - XWAVEHDR* result = Globals->WaveBlockArray[index]; - result->fAvailable = 0; - result->wh.dwBufferLength = Globals->dwWaveBlockLen; - result->wh.lpData = reinterpret_cast(&result[1]); - result->g = GlobalsActive; - return result; -} - -int WaveMix::MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks) -{ - if (!lpXWH) - return 0; - - unsigned minStartPos = -1; - auto playChannelCount = 0; - auto channelPtr = Globals->aChannel; - for (auto channelIndex = 16; channelIndex; --channelIndex) - { - auto channel = *channelPtr; - if (channel != reinterpret_cast(-1) && channel) - { - do - { - if (channel->dwEndPos > Globals->dwCurrentSample) - break; - channel = channel->next; - } - while (channel); - if (channel) - { - if (channel->dwStartPos < minStartPos) - minStartPos = channel->dwStartPos; - play_channel_array[playChannelCount++] = channel; - } - } - ++channelPtr; - } - if (!playChannelCount) - { - if (fWriteBlocks) - lpXWH->fAvailable = 1; - return 0; - } - - auto currentSample = Globals->dwCurrentSample; - auto dataPtr = reinterpret_cast(lpXWH->wh.lpData); - auto waveBlockLen = Globals->dwWaveBlockLen; - while (waveBlockLen) - { - if (currentSample >= minStartPos) - { - auto waveCount = 0; - auto endBlockPosition = currentSample + waveBlockLen; - - for (auto channelIndex = 0; channelIndex < playChannelCount; ++channelIndex) - { - auto channel = play_channel_array[channelIndex]; - if (channel->dwStartPos <= currentSample) - { - if (channel->dwEndPos < endBlockPosition) - endBlockPosition = channel->dwEndPos; - auto dataOffset = currentSample - channel->dwStartPos; - if (channel->PlayParams.wLoops) - { - dataOffset %= channel->dwNumSamples; - auto endBlockPosition2 = currentSample + (channel->dwNumSamples - dataOffset); - if (endBlockPosition2 < endBlockPosition) - endBlockPosition = endBlockPosition2; - } - play_data[waveCount] = &channel->lpPos[dataOffset]; - play_volume[waveCount].L = channel->Volume.L; - play_volume[waveCount].R = channel->Volume.R; - waveCount++; - } - else if (channel->dwStartPos < endBlockPosition) - { - endBlockPosition = channel->dwStartPos; - } - } - - if (waveCount) - { - auto dataLength = endBlockPosition - currentSample; - Globals->CmixPtr(dataPtr, play_data, play_volume, waveCount, static_cast(dataLength)); - - dataPtr += dataLength; - waveBlockLen -= dataLength; - minStartPos = -1; - currentSample += dataLength; - - - auto playChPtr = play_channel_array; - for (auto channelIndex = 0; channelIndex < playChannelCount;) - { - while (*playChPtr) - { - if ((*playChPtr)->dwEndPos > currentSample) - break; - *playChPtr = (*playChPtr)->next; - } - if (*playChPtr) - { - if ((*playChPtr)->dwStartPos < minStartPos) - minStartPos = (*playChPtr)->dwStartPos; - ++channelIndex; - ++playChPtr; - } - else - { - playChannelCount--; - *playChPtr = play_channel_array[playChannelCount]; - if (!playChannelCount) - break; - } - } - } - } - else - { - auto length = waveBlockLen; - if (waveBlockLen + currentSample >= minStartPos) - length = minStartPos - currentSample; - memset(dataPtr, 0x80u, length); - dataPtr += length; - currentSample += length; - waveBlockLen -= length; - } - } - - lpXWH->dwWavePos = Globals->dwCurrentSample; - Globals->dwCurrentSample += Globals->dwWaveBlockLen; - if (fWriteBlocks) - { - AddToPlayingQueue(lpXWH); - if (waveOutWrite(Globals->hWaveOut, &lpXWH->wh, sizeof(WAVEHDR))) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to write block to device", "WavMix32", MB_ICONWARNING); - lpXWH->fAvailable = 1; - RemoveFromPlayingQueue(lpXWH); - } - } - return 1; -} - -XWAVEHDR* WaveMix::AddToPlayingQueue(XWAVEHDR* lpXWH) -{ - lpXWH->QNext = nullptr; - if (play_queue.first) - { - play_queue.last->QNext = lpXWH; - } - else - { - play_queue.first = lpXWH; - } - play_queue.last = lpXWH; - return play_queue.first; -} - -void WaveMix::MyWaveOutReset(HWAVEOUT hWaveOut) -{ - auto position = MyWaveOutGetPosition(hWaveOut, Globals->fGoodGetPos); - waveOutReset(hWaveOut); - SetWaveOutPosition(position); -} - -void WaveMix::SetWaveOutPosition(unsigned newPosition) -{ - DWORD position; - mmtime_tag pmmt{}; - - pmmt.wType = TIME_BYTES; - if (Globals->hWaveOut) - { - waveOutGetPosition(Globals->hWaveOut, &pmmt, 0xCu); - position = pmmt.u.ms; /*Todo: check union ms vs sample with TIME_BYTES*/ - } - else - { - position = 0; - } - - if (position < newPosition) - { - Globals->dwWaveOutPos = newPosition - position; - Globals->pfnSampleAdjust = AddFactor; - } - else - { - Globals->dwWaveOutPos = position - newPosition; - Globals->pfnSampleAdjust = SubFactor; - } - Globals->dwCurrentSample = newPosition; - Globals->dwBaseTime = timeGetTime() - 1000 * newPosition / Globals->PCM.wf.nAvgBytesPerSec; -} - -DWORD WaveMix::SubFactor(DWORD a1, DWORD a2) -{ - return a1 - a2; -} - -DWORD WaveMix::AddFactor(DWORD a1, DWORD a2) -{ - return a1 + a2; -} - -dialog_template* WaveMix::MakeSettingsDlgTemplate() -{ - size_t size = 0u; - dialog_template* temp = MakeDlgTemplate(&size, 0x80C80080, 0, 0, 212, 132, L"WavMix32 Settings (Ver %X.%X Static)"); - temp = AddDlgControl(&size, temp, 128, 65537, 1, 155, 5, 50, 14, L"&Ok"); - temp = AddDlgControl(&size, temp, 128, 0x10000, 2, 155, 25, 50, 14, L"&Cancel"); - temp = AddDlgControl(&size, temp, 130, 0, 1012, 5, 5, 115, 8, L"Number of WaveBlocks (%d-%d):"); - temp = AddDlgControl(&size, temp, 130, 0, 1013, 5, 20, 115, 8, L"Size of WaveBlocks (%d-%d):"); - temp = AddDlgControl(&size, temp, 130, 0, 0xFFFF, 5, 35, 102, 8, L"Playback Frequency (11,22,44):"); - temp = AddDlgControl(&size, temp, 130, 0, 0xFFFF, 5, 80, 57, 8, L"Playback Device:"); - temp = AddDlgControl(&size, temp, 130, 0, 1014, 5, 50, 115, 8, L"Number of Pause Blocks (%d-%d):"); - temp = AddDlgControl(&size, temp, 130, 0, 1015, 5, 65, 63, 8, L"Max Channels = %d"); - temp = AddDlgControl(&size, temp, 129, 8454272, 1003, 125, 5, 25, 12, L"-1"); - temp = AddDlgControl(&size, temp, 129, 8454272, 1007, 125, 20, 25, 12, L"-1"); - temp = AddDlgControl(&size, temp, 129, 8454272, 1008, 125, 35, 25, 12, L"-1"); - temp = AddDlgControl(&size, temp, 129, 8454272, 1011, 125, 50, 25, 12, L"-1"); - temp = AddDlgControl(&size, temp, 133, 2162946, 1009, 65, 80, 140, 60, L"No Devices"); - temp = AddDlgControl(&size, temp, 128, 65539, 1000, 5, 101, 40, 10, L"Stereo"); - temp = AddDlgControl(&size, temp, 128, 65539, 1001, 55, 101, 60, 10, L"Reset Remix"); - temp = AddDlgControl(&size, temp, 128, 65539, 1010, 125, 101, 78, 10, L"Show Debug Dialogs"); - temp = AddDlgControl(&size, temp, 128, 65539, 1005, 5, 117, 40, 10, L"CMixit"); - return AddDlgControl(&size, temp, 128, 65539, 1004, 55, 117, 75, 10, L"Good Get Position"); -} - -dialog_template* WaveMix::MakeDlgTemplate(size_t* totalSize, unsigned style, short x, short y, short cx, short cy, - const wchar_t* String) -{ - auto dlgSize = 2 * wcslen(String) + 24; - *totalSize = dlgSize; - if ((dlgSize & 3) != 0) - *totalSize = dlgSize - (dlgSize & 3) + 4; - - auto hGlobal = GlobalAlloc(GHND, *totalSize); - auto dlgTemplate = static_cast(GlobalLock(hGlobal)); - if (dlgTemplate) - { - dlgTemplate->Dialog.dwExtendedStyle = 0; - dlgTemplate->Dialog.cdit = 0; - dlgTemplate->Dialog.style = style | 0x10000000; - dlgTemplate->Dialog.x = x; - dlgTemplate->Dialog.y = y; - dlgTemplate->Dialog.cx = cx; - dlgTemplate->Dialog.cy = cy; - memcpy(dlgTemplate->Header, String, 2 * wcslen(String) + 2); - } - return dlgTemplate; -} - -dialog_template* WaveMix::AddDlgControl(size_t* totalSize, dialog_template* dlgTemplate, short idClass, - unsigned style, WORD id, short x, short y, short cx, short cy, - const wchar_t* String) -{ - dialog_template* dlgTemplate2 = dlgTemplate; - if (dlgTemplate) - { - auto prevSize = *totalSize; - *totalSize += 2 * wcslen(String) + 25; - if ((*totalSize & 3) != 0) - *totalSize = *totalSize - (*totalSize & 3) + 4; - - GlobalUnlock(GlobalHandle(dlgTemplate2)); - auto newSize = *totalSize; - HGLOBAL hGlobal = GlobalReAlloc(GlobalHandle(dlgTemplate2), newSize, 0x42u); - dlgTemplate2 = static_cast(GlobalLock(hGlobal)); - if (dlgTemplate2) - { - auto dlgItem = (dialog_item_template*)((char*)dlgTemplate2 + prevSize); - dlgItem->Item.dwExtendedStyle = 0; - dlgItem->Item.style = style | 0x50000000; - dlgItem->Item.x = x; - dlgItem->Item.y = y; - dlgItem->Item.cx = cx; - dlgItem->Item.cy = cy; - dlgItem->Item.id = id; - dlgItem->sysClass = 0xFFFF; - dlgItem->idClass = idClass; - wcscpy_s(dlgItem->Header, wcslen(String) + 1, String); - ++dlgTemplate2->Dialog.cdit; - } - } - return dlgTemplate2; -} - -void WaveMix::DestroySettingsDlgTemplate(LPCVOID pMem) -{ - if (pMem) - { - GlobalUnlock(GlobalHandle(pMem)); - GlobalFree(GlobalHandle(pMem)); - } -} - -int WaveMix::Settings_OnInitDialog(HWND hWnd, WPARAM wParam, MIXCONFIG* lpMixconfig) -{ - tagWAVEOUTCAPSA pwoc{}; - CHAR String[256]; - - GetWindowTextA(hWnd, String, 256); - wsprintfA(string_buffer, String, 2, 81); - SetWindowTextA(hWnd, string_buffer); - SetWindowLongPtr(hWnd, -21, reinterpret_cast(lpMixconfig)); - SendMessageA(GetDlgItem(hWnd, 1000), 0xF1u, lpMixconfig->wChannels > 1u, 0); - SendMessageA(GetDlgItem(hWnd, 1001), 0xF1u, lpMixconfig->ResetMixDefaultFlag != 0, 0); - SendMessageA(GetDlgItem(hWnd, 1004), 0xF1u, lpMixconfig->GoodWavePos != 0, 0); - SendMessageA(GetDlgItem(hWnd, 1005), 0xF1u, lpMixconfig->CmixPtrDefaultFlag != 0, 0); - SendMessageA(GetDlgItem(hWnd, 1010), 0xF1u, lpMixconfig->ShowDebugDialogs != 0, 0); - EnableWindow(GetDlgItem(hWnd, 1005), 0); - SendMessageA(GetDlgItem(hWnd, 1003), 0xC5u, 2u, 0); - SendMessageA(GetDlgItem(hWnd, 1007), 0xC5u, 4u, 0); - SendMessageA(GetDlgItem(hWnd, 1008), 0xC5u, 2u, 0); - SendMessageA(GetDlgItem(hWnd, 1011), 0xC5u, 2u, 0); - GetWindowTextA(GetDlgItem(hWnd, 1012), String, 100); - wsprintfA(string_buffer, String, 2, 10); - SetWindowTextA(GetDlgItem(hWnd, 1012), string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1013), String, 100); - wsprintfA(string_buffer, String, 344, 11025); - SetWindowTextA(GetDlgItem(hWnd, 1013), string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1014), String, 100); - wsprintfA(string_buffer, String, 0, 10); - SetWindowTextA(GetDlgItem(hWnd, 1014), string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1015), String, 100); - wsprintfA(string_buffer, String, 16); - SetWindowTextA(GetDlgItem(hWnd, 1015), string_buffer); - wsprintfA(string_buffer, "%d", lpMixconfig->WaveBlockCount); - SetWindowTextA(GetDlgItem(hWnd, 1003), string_buffer); - wsprintfA(string_buffer, "%d", lpMixconfig->WaveBlockLen); - SetWindowTextA(GetDlgItem(hWnd, 1007), string_buffer); - wsprintfA(string_buffer, "%d", lpMixconfig->wSamplingRate); - SetWindowTextA(GetDlgItem(hWnd, 1008), string_buffer); - wsprintfA(string_buffer, "%d", lpMixconfig->PauseBlocks); - SetWindowTextA(GetDlgItem(hWnd, 1011), string_buffer); - - signed int uDeviceID = 0; - signed int deviceCount = waveOutGetNumDevs(); - if (deviceCount > 0) - { - do - { - MMRESULT getResult = waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u); - if (getResult) - { - wsprintfA(string_buffer, "waveOutGetDevCaps failed (err %u) for device %d", getResult, uDeviceID); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); - } - else - { - wsprintfA(string_buffer, "%d: %s", uDeviceID, pwoc.szPname); - SendMessageA(GetDlgItem(hWnd, 1009), 0x143u, 0, (LPARAM)string_buffer); - } - ++uDeviceID; - } - while (uDeviceID < deviceCount); - } - SendMessageA(GetDlgItem(hWnd, 1009), 0x14Eu, lpMixconfig->wDeviceID, 0); - return 1; -} - -int WaveMix::Settings_OnCommand(HWND hWnd, int command, LPARAM lParam, int wParam) -{ - auto userData = reinterpret_cast(GetWindowLongPtrA(hWnd, -21)); - if (command == 1) - { - if (userData) - { - userData->wChannels = (SendMessageA(GetDlgItem(hWnd, 1000), 0xF0u, 0, 0) != 0) + 1; - userData->ResetMixDefaultFlag = SendMessageA(GetDlgItem(hWnd, 1001), 0xF0u, 0, 0) != 0; - userData->GoodWavePos = SendMessageA(GetDlgItem(hWnd, 1004), 0xF0u, 0, 0) != 0; - userData->ShowDebugDialogs = SendMessageA(GetDlgItem(hWnd, 1010), 0xF0u, 0, 0) != 0; - userData->CmixPtrDefaultFlag = SendMessageA(GetDlgItem(hWnd, 1005), 0xF0u, 0, 0) != 0; - GetWindowTextA(GetDlgItem(hWnd, 1003), string_buffer, 10); - userData->WaveBlockCount = atoi(string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1007), string_buffer, 10); - userData->WaveBlockLen = atoi(string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1008), string_buffer, 10); - userData->wSamplingRate = atoi(string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1011), string_buffer, 10); - userData->PauseBlocks = atoi(string_buffer); - GetWindowTextA(GetDlgItem(hWnd, 1009), string_buffer, 10); - userData->wDeviceID = isdigit(string_buffer[0]) ? atoi(string_buffer) : 0; - EndDialog(hWnd, 1); - } - } - else - { - if (command != 2) - return 0; - EndDialog(hWnd, 0); - } - return 1; -} - -int WaveMix::ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength) -{ - HKEY phkResult; - CHAR SubKey[52]; - - int result = 0; - int osPrefixLength = lstrlenA(GetOperatingSystemPrefix()); - if (maxLength < osPrefixLength + 10) - return 0; - wsprintfA(SubKey, "Device%u", wDeviceId); - if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\WaveMix", &phkResult)) - return 0; - lstrcpyA(lpString1, GetOperatingSystemPrefix()); - LONG cbData = maxLength - osPrefixLength; - if (!RegQueryValueA(phkResult, SubKey, &lpString1[osPrefixLength], &cbData) && cbData > 0) - result = 1; - RegCloseKey(phkResult); - return result; -} - -#pragma warning (disable : 4996)/*Original uses GetVersion*/ -const char* WaveMix::GetOperatingSystemPrefix() -{ - if (GetVersion() < 0x80000000) - return "WinNT:"; - if (GetVersion() >= 0x80000000 && static_cast(GetVersion()) >= 4u) - return "Win95:"; - if (GetVersion() >= 0x80000000 && static_cast(GetVersion()) < 4u) - return "Win31:"; - return "OS_X"; /*The next big thing: waveOut on OSX*/ -} -#pragma warning (default : 4996)/*Original uses GetVersion*/ - -unsigned WaveMix::FigureOutDMABufferSize(unsigned waveBlockLen, PCMWAVEFORMAT* pcm) -{ - unsigned int result = waveBlockLen; - if (!waveBlockLen) - result = pcm->wf.nSamplesPerSec * pcm->wf.nChannels * (pcm->wBitsPerSample >> 3) >> 4; - if (result < 344) - result = 344; - if (result > 11025) - result = 11025; - return result; -} - -int WaveMix::NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel) -{ - Pump(); - return 1; -} - -void WaveMix::SaveConfigSettings(unsigned dwFlags) -{ - if ((dwFlags & 0x80u) != 0) - { - wsprintfA(string_buffer, "%d", Globals->wDeviceID); - WritePrivateProfileStringA("general", "WaveOutDevice", string_buffer, FileName); - } - if ((dwFlags & 1) != 0) - { - wsprintfA(string_buffer, "%d", Globals->PCM.wf.nChannels); - WritePrivateProfileStringA(Globals->szDevicePName, "Channels", string_buffer, FileName); - } - if ((dwFlags & 2) != 0) - { - wsprintfA(string_buffer, "%d", static_cast(11 * (Globals->PCM.wf.nSamplesPerSec / 0x2B11))); - WritePrivateProfileStringA(Globals->szDevicePName, "SamplesPerSec", string_buffer, FileName); - } - if ((dwFlags & 4) != 0) - { - wsprintfA(string_buffer, "%d", Globals->WaveBlockCount); - WritePrivateProfileStringA(Globals->szDevicePName, "WaveBlocks", string_buffer, FileName); - } - if ((dwFlags & 8) != 0) - { - wsprintfA(string_buffer, "%d", LOWORD(WaveMix::Globals->dwWaveBlockLen)); - WritePrivateProfileStringA(Globals->szDevicePName, "WaveBlockLen", string_buffer, FileName); - } - if ((dwFlags & 0x10) != 0) - { - wsprintfA(string_buffer, "%d", Globals->CmixPtr == cmixit); - WritePrivateProfileStringA(Globals->szDevicePName, "CMixit", string_buffer, FileName); - } - if ((dwFlags & 0x20) != 0) - { - wsprintfA(string_buffer, "%d", (Globals->pfnRemix != ResetRemix) + 1); - WritePrivateProfileStringA(Globals->szDevicePName, "Remix", string_buffer, FileName); - } - if ((dwFlags & 0x40) != 0) - { - wsprintfA(string_buffer, "%d", Globals->fGoodGetPos == 0); - WritePrivateProfileStringA(Globals->szDevicePName, "GoodWavePos", string_buffer, FileName); - } - if ((dwFlags & 0x100) != 0) - { - wsprintfA(string_buffer, "%d", ShowDebugDialogs != 0); - WritePrivateProfileStringA("general", "ShowDebugDialogs", string_buffer, FileName); - } - if ((dwFlags & 0x200) != 0) - { - wsprintfA(string_buffer, "%d", Globals->PauseBlocks); - WritePrivateProfileStringA(Globals->szDevicePName, "PauseBlocks", string_buffer, FileName); - } -} - -void WaveMix::ShowCurrentSettings() -{ - tagWAVEOUTCAPSA pwoc{}; - - if (waveOutGetDevCapsA(Globals->wDeviceID, &pwoc, 0x34u) || !RemoveInvalidIniNameCharacters(pwoc.szPname)) - lstrcpyA(pwoc.szPname, "Unknown Device"); - auto cmixitType = "cmixit"; - if (Globals->CmixPtr != cmixit) - cmixitType = "386 mixit"; - auto getGood = "TRUE"; - if (!Globals->fGoodGetPos) - getGood = "FALSE"; - auto remixType = "Reset"; - if (Globals->pfnRemix != ResetRemix) - remixType = "NoReset"; - wsprintfA( - string_buffer, - "Using:\t%s.\n" - "\tRemix = %s\n" - "\tGoodGetPos=%s\n" - "\t%d ping pong wave blocks\n" - "\tWave block len = %lu bytes\n" - "\tpfnMixit=%s\n" - "\tSamplesPerSec=%lu,\n" - "\tChannels=%d\n" - "\tPauseBlocks=%d", - pwoc.szPname, - remixType, - getGood, - Globals->WaveBlockCount, - Globals->dwWaveBlockLen, - cmixitType, - Globals->PCM.wf.nSamplesPerSec, - Globals->PCM.wf.nChannels, - Globals->PauseBlocks); - MessageBoxA(nullptr, string_buffer, "WavMix32", MB_ICONINFORMATION); -} - -unsigned WaveMix::GetWaveDevice() -{ - WAVEFORMATEX pwfx{}; - - if (Globals->hWaveOut) - return 0; - HWND window = CreateWindowExA(0, "WavMix32", "", 0x8000000u, 0, 0, 0, 0, nullptr, nullptr, HModule, - nullptr); - GLOBALS* globals = Globals; - Globals->hWndApp = window; - if (!window) - { - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Failed to create callback window.", "WavMix32", MB_ICONWARNING); - return 1; - } - pwfx.wFormatTag = globals->PCM.wf.wFormatTag; - pwfx.nChannels = globals->PCM.wf.nChannels; - pwfx.nSamplesPerSec = globals->PCM.wf.nSamplesPerSec; - pwfx.nAvgBytesPerSec = globals->PCM.wf.nAvgBytesPerSec; - pwfx.nBlockAlign = globals->PCM.wf.nBlockAlign; - pwfx.wBitsPerSample = globals->PCM.wBitsPerSample; - pwfx.cbSize = 0; - unsigned int openResult = waveOutOpen(&globals->hWaveOut, 0xFFFFFFFF, &pwfx, - reinterpret_cast(globals->hWndApp), 0, - 0x10000u); - if (openResult) - { - DestroyWindow(Globals->hWndApp); - Globals->hWndApp = nullptr; - return openResult; - } - if (AllocWaveBlocks(Globals->hWaveOut, block_array1) - && AllocWaveBlocks(Globals->hWaveOut, block_array2)) - { - Globals->WaveBlockArray = block_array1; - return 0; - } - FreeWaveBlocks(Globals->hWaveOut, block_array1); - FreeWaveBlocks(Globals->hWaveOut, block_array2); - waveOutClose(Globals->hWaveOut); - Globals->hWaveOut = nullptr; - DestroyWindow(Globals->hWndApp); - return 1; -} - -void WaveMix::FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks) -{ - for (int i = 0; i < 10; ++i) - { - auto blockPtr = &waveBlocks[i]; - if (*blockPtr) - { - waveOutUnprepareHeader(hwo, &(*blockPtr)->wh, sizeof(WAVEHDR)); - GlobalUnlock(GlobalHandle(*blockPtr)); - GlobalFree(GlobalHandle(*blockPtr)); - *blockPtr = nullptr; - } - } -} - -int WaveMix::AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks) -{ - for (int i = 0; i < 10; ++i) - { - auto xHDR = static_cast(GlobalLock(GlobalAlloc(GMEM_SHARE, 0x2B41u))); - waveBlocks[i] = xHDR; - if (!xHDR) - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONWARNING); - for (int j = i - 1; j >= 0; --j) - { - GlobalUnlock(GlobalHandle(waveBlocks[j])); - GlobalFree(GlobalHandle(waveBlocks[j])); - waveBlocks[j] = nullptr; - } - return 0; - } - xHDR->wh.lpData = (LPSTR)&xHDR[1]; - xHDR->wh.dwBufferLength = Globals->dwWaveBlockLen; - xHDR->wh.dwFlags = 0; - xHDR->wh.dwLoops = 0; - xHDR->fAvailable = 1; - xHDR->dwWavePos = 0; - } - int index = 0; - while (!waveOutPrepareHeader(hwo, &waveBlocks[index]->wh, sizeof(WAVEHDR))) - { - waveBlocks[index++]->wh.dwFlags |= 1u; - if (index >= 10) - return 1; - } - if (ShowDebugDialogs) - MessageBoxA(nullptr, "Unable to prepare wave header.", "WavMix32", MB_ICONWARNING); - FreeWaveBlocks(hwo, waveBlocks); - return 0; -} - -void WaveMix::ReleaseWaveDevice(GLOBALS* globals) -{ - if (globals->fActive) - { - if (globals->hWaveOut) - { - MyWaveOutReset(globals->hWaveOut); - DestroyPlayQueue(); - FreeWaveBlocks(globals->hWaveOut, block_array1); - FreeWaveBlocks(globals->hWaveOut, block_array2); - waveOutClose(globals->hWaveOut); - globals->hWaveOut = nullptr; - DestroyWindow(globals->hWndApp); - globals->hWndApp = nullptr; - } - } -} - -HPSTR WaveMix::WaveFormatConvert(PCMWAVEFORMAT* lpOutWF, PCMWAVEFORMAT* lpInWF, HPSTR lpInData, DWORD* dwDataSize) -{ - if (lpInWF->wf.nChannels == lpOutWF->wf.nChannels && - lpInWF->wf.nSamplesPerSec == lpOutWF->wf.nSamplesPerSec && - lpInWF->wBitsPerSample == lpOutWF->wBitsPerSample) - { - return lpInData; - } - HPSTR dataBuf = BitsPerSampleAlign(lpInData, lpInWF->wBitsPerSample, lpOutWF->wBitsPerSample, dwDataSize); - if (!dataBuf) - return nullptr; - dataBuf = ChannelAlign(dataBuf, lpInWF->wf.nChannels, lpOutWF->wf.nChannels, lpOutWF->wBitsPerSample / 8, - dwDataSize); - if (!dataBuf) - return nullptr; - dataBuf = SamplesPerSecAlign(dataBuf, lpInWF->wf.nSamplesPerSec, lpOutWF->wf.nSamplesPerSec, - lpOutWF->wBitsPerSample / 8, lpOutWF->wf.nChannels, dwDataSize); - return dataBuf; -} - -HPSTR WaveMix::BitsPerSampleAlign(HPSTR lpInData, WORD nInBPS, WORD nOutBPS, DWORD* dwDataSize) -{ - LPVOID dataBuf = nullptr; - - if (nInBPS == nOutBPS) - return lpInData; - - if ((nInBPS == 8 || nInBPS == 16) && (nOutBPS == 8 || nOutBPS == 16)) - { - DWORD dwNumSamples = *dwDataSize / (nInBPS / 8u); - *dwDataSize = dwNumSamples * (nOutBPS / 8u); - - dataBuf = GlobalLock(GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, *dwDataSize)); - if (dataBuf) - { - if (nInBPS / 8u <= nOutBPS / 8u) - { - auto dst = static_cast(dataBuf); - for (auto src = lpInData; dwNumSamples; --dwNumSamples) - *dst++ = static_cast((*src++ - 128) * 256); - } - else - { - auto dst = static_cast(dataBuf); - for (auto src = reinterpret_cast(lpInData); dwNumSamples; --dwNumSamples) - { - *dst++ = static_cast(*src++ / 256 + 128); - } - } - } - else - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONINFORMATION); - } - } - - GlobalUnlock(GlobalHandle(lpInData)); - GlobalFree(GlobalHandle(lpInData)); - return static_cast(dataBuf); -} - -HPSTR WaveMix::ChannelAlign(HPSTR lpInData, WORD nInChannels, WORD nOutChannels, WORD nBytesPerSample, - DWORD* dwDataSize) -{ - if (nInChannels == nOutChannels) - return lpInData; - DWORD dwNumSamples = *dwDataSize / nBytesPerSample / nInChannels; - *dwDataSize = dwNumSamples * nBytesPerSample * nOutChannels; - char* dataBuf = static_cast(GlobalLock(GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, *dwDataSize))); - if (dataBuf) - { - if (nInChannels < nOutChannels) - { - if (nBytesPerSample == 1) - { - auto src = lpInData; - auto dst = dataBuf; - for (; dwNumSamples; --dwNumSamples) - { - *dst++ = *src; - *dst++ = *src++; - } - } - else - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(dataBuf); - for (; dwNumSamples; --dwNumSamples) - { - *dst++ = *src; - *dst++ = *src++; - } - } - } - else - { - if (nBytesPerSample == 1) - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(dataBuf); - for (; dwNumSamples; --dwNumSamples, src += 2) - { - *dst++ = static_cast((src[0] + src[1]) / 2); - } - } - else - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(dataBuf); - for (; dwNumSamples; --dwNumSamples, src += 2) - { - *dst++ = static_cast((src[0] + src[1]) / 2); - } - } - } - } - else - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONINFORMATION); - dataBuf = nullptr; - } - - GlobalUnlock(GlobalHandle(lpInData)); - GlobalFree(GlobalHandle(lpInData)); - return dataBuf; -} - -HPSTR WaveMix::SamplesPerSecAlign(HPSTR lpInData, DWORD nInSamplesPerSec, DWORD nOutSamplesPerSec, WORD nBytesPerSample, - WORD nChannels, DWORD* dwDataSize) -{ - if (nInSamplesPerSec == nOutSamplesPerSec) - return lpInData; - auto sampleSize = nBytesPerSample * nChannels; - auto dwNumSamples = *dwDataSize / sampleSize; - unsigned int nRep, nSkip, dwNumSamples2; - if (nOutSamplesPerSec <= nInSamplesPerSec) - { - nRep = 0; - nSkip = nInSamplesPerSec / nOutSamplesPerSec; - dwNumSamples2 = dwNumSamples / nSkip; - } - else - { - nSkip = 0; - nRep = nOutSamplesPerSec / nInSamplesPerSec; - dwNumSamples2 = dwNumSamples * nRep; - } - *dwDataSize = sampleSize * dwNumSamples2; - - auto dataBuf = static_cast(GlobalLock(GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sampleSize * dwNumSamples2))); - if (!dataBuf) - { - if (ShowDebugDialogs) - MessageBoxA( - nullptr, - "Unable to allocate memory for waveform data. Try making more memory available by closing other applications.", - "WavMix32", - MB_ICONINFORMATION); - GlobalUnlock(GlobalHandle(lpInData)); - GlobalFree(GlobalHandle(lpInData)); - return nullptr; - } - - auto lpInDataBup = lpInData; - auto dataBufBup = dataBuf; - if (nRep <= 0) - { - for (auto index = dwNumSamples2 - 1; index; --index) - { - AvgSample(dataBuf, lpInData, nSkip, nBytesPerSample, nChannels); - lpInData += sampleSize * nSkip; - dataBuf += sampleSize; - } - for (; sampleSize; --sampleSize) - *dataBuf++ = *lpInData++; - } - else - { - for (auto index = dwNumSamples - 1; index; --index) - { - RepSample(dataBuf, lpInData, nRep, nBytesPerSample, nChannels); - lpInData += sampleSize; - dataBuf += sampleSize * nRep; - } - for (auto index1 = nRep; index1; --index1) - { - auto src = lpInData; - for (auto index2 = sampleSize; index2; --index2) - *dataBuf++ = *src++; - } - } - - // Dump raw PCM for analysis. - /*FILE* file; - fopen_s(&file,"wav1_dump.raw", "w"); - fwrite(dataBufBup, 1, sampleSize * dwNumSamples2, file); - fclose(file);*/ - - GlobalUnlock(GlobalHandle(lpInDataBup)); - GlobalFree(GlobalHandle(lpInDataBup)); - return dataBufBup; -} - -void WaveMix::AvgSample(HPSTR lpOutData, HPSTR lpInData, unsigned nSkip, int nBytesPerSample, int nChannels) -{ - if (nBytesPerSample == 1) - { - auto dst = lpOutData; - for (auto channelIndex = nChannels; channelIndex; --channelIndex) - { - auto src = lpInData++; - auto average = 0; - for (auto avgIndex = nSkip; avgIndex; --avgIndex) - { - average += static_cast(*src) - 128; - src += nChannels; - } - *dst++ = static_cast(average / nSkip + 128); - } - } - else - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(lpOutData); - for (auto channelIndex = nChannels; channelIndex; --channelIndex) - { - auto curSrc = src++; - auto average2 = 0; - for (auto avgIndex = nSkip; avgIndex; --avgIndex) - { - average2 += *curSrc; - curSrc += nChannels; - } - *dst++ = static_cast(average2 / nSkip); /*Was *dst = */ - } - } -} - -void WaveMix::RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nBytesPerSample, int nChannels) -{ - if (nBytesPerSample == 1) - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(lpOutData); - for (auto channelIndex = nChannels; channelIndex; --channelIndex) - { - auto sample = *src; - auto dst2 = &dst[nChannels]; - auto delta = (src[nChannels] - src[0]) / static_cast(nRep); - *dst = *src; - dst++; - for (auto repeatIndex = nRep - 1; repeatIndex; repeatIndex--) - { - sample += delta; - *dst2 = sample; - dst2 += nChannels; - } - ++src; - } - } - else - { - auto src = reinterpret_cast(lpInData); - auto dst = reinterpret_cast(lpOutData); - for (auto channelIndex2 = nChannels; channelIndex2; channelIndex2--) - { - auto sample = *src; - auto dst2 = &dst[nChannels]; - auto delta = (src[nChannels] - src[0]) / static_cast(nRep); /*Was dst[nChannels] - */ - *dst = *src; - ++dst; - for (auto repeatIndex2 = nRep - 1; repeatIndex2; --repeatIndex2) - { - sample += delta; - *dst2 = sample; - dst2 += nChannels; - } - ++src; - } - } -} - -bool WaveMix::IsValidLPMIXWAVE(MIXWAVE* lpMixWave) -{ - return lpMixWave && lpMixWave->wMagic == 21554; -} - -void WaveMix::FreePlayedBlocks() -{ - auto position = MyWaveOutGetPosition(Globals->hWaveOut, Globals->fGoodGetPos); - for (int i = 0; i < MAXCHANNELS; i ++) - { - CHANNELNODE* channel = Globals->aChannel[i]; - if (channel && channel != reinterpret_cast(-1)) - { - while (channel && position >= channel->dwEndPos) - { - Globals->aChannel[i] = channel->next; - if (channel->PlayParams.hWndNotify) - PostMessageA(channel->PlayParams.hWndNotify, MM_WOM_DONE, i, - reinterpret_cast(channel->lpMixWave)); - FreeChannelNode(channel); - channel = Globals->aChannel[i]; - } - } - } - if (!Globals->fGoodGetPos && !play_queue.first) - { - for (int i = 0; i < MAXCHANNELS; i++) - { - auto channel = Globals->aChannel[i]; - if (channel) - { - if (channel != reinterpret_cast(-1)) - { - PostMessageA(Globals->hWndApp, 0x400u, 0, reinterpret_cast(Globals)); - } - } - } - } -} - -int WaveMix::HasCurrentOutputFormat(MIXWAVE* lpMixWave) -{ - return memcmp(&lpMixWave->pcm, &Globals->PCM, sizeof(PCMWAVEFORMAT)) == 0; -} - -CHANNELNODE* WaveMix::GetChannelNode() -{ - CHANNELNODE* result = free_channel_nodes; - if (result) - { - free_channel_nodes = free_channel_nodes->next; - result->next = nullptr; - } - return result; -} - -void WaveMix::ResetWavePosIfNoChannelData() -{ - if (!play_queue.first) - { - int channelIndex = 0; - for (CHANNELNODE** i = Globals->aChannel; !*i || *i == reinterpret_cast(-1); ++i) - { - if (++channelIndex >= 16) - { - SetWaveOutPosition(0); - return; - } - } - } -} - -void WaveMix::cmixit(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volumeArr, int iNumWaves, - uint16_t length) -{ - if (!length) - return; - - if (Globals->PCM.wf.nChannels == 2) - { - if (iNumWaves == 1) - { - auto src = rgWaveSrc[0]; - for (auto index = (length - 1u) / 2u + 1u; index; --index) - { - *lpDest++ = volume_table[volumeArr->L][*src++]; - *lpDest++ = volume_table[volumeArr->R][*src++]; - } - } - else - { - for (auto srcOffset = 0u, index = (length - 1u) / 2u + 1u; index; index--) - { - auto sampleR = 128; - auto sampleL = 128; - auto volumePtr = volumeArr; - for (auto channelIndex = 0; channelIndex < iNumWaves; channelIndex++) - { - auto src = rgWaveSrc[channelIndex] + srcOffset; - sampleL += volume_table[volumePtr->L][src[0]] - 128; - sampleR += volume_table[volumePtr->R][src[1]] - 128; - ++volumePtr; - } - - srcOffset += 2; - lpDest[0] = min(max(sampleL, 0), 255); - lpDest[1] = min(max(sampleR, 0), 255); - lpDest += 2; - } - } - } - else - { - if (iNumWaves == 1) - { - auto src = rgWaveSrc[0]; - auto avgVolume = (volumeArr->L + volumeArr->R) / 2; - for (auto index = length; index; --index) - *lpDest++ = volume_table[avgVolume][*src++]; - } - else - { - for (unsigned srcOffset = 0u, index = length; index; index--) - { - auto sample = 128; - auto volumePtr = volumeArr; - for (auto channelIndex = 0; channelIndex < iNumWaves; channelIndex++) - { - auto src = rgWaveSrc[channelIndex] + srcOffset; - auto curSample = volume_table[(volumePtr->L + volumePtr->R) / 2][src[0]]; - sample += curSample - 128; - ++volumePtr; - } - - ++srcOffset; - *lpDest++ = min(max(sample, 0), 255); - } - } - } -} - -LRESULT WaveMix::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - if (Msg != MM_WOM_DONE && Msg != WM_USER) - return DefWindowProcA(hWnd, Msg, wParam, lParam); - Pump(); - return 0; -} - -INT_PTR WaveMix::SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - if (Msg == WM_INITDIALOG) - return Settings_OnInitDialog(hWnd, wParam, reinterpret_cast(lParam)); - if (Msg != WM_COMMAND) - return 0; - Settings_OnCommand(hWnd, LOWORD(wParam), lParam, HIWORD(wParam)); - return 1; -} diff --git a/SpaceCadetPinball/WaveMix.h b/SpaceCadetPinball/WaveMix.h deleted file mode 100644 index d089938..0000000 --- a/SpaceCadetPinball/WaveMix.h +++ /dev/null @@ -1,244 +0,0 @@ -#pragma once - - -/* flag values for play params */ -#define WMIX_QUEUEWAVE 0x00 -#define WMIX_CLEARQUEUE 0x01 -#define WMIX_USELRUCHANNEL 0x02 -#define WMIX_HIPRIORITY 0x04 -#define WMIX_WAIT 0x08 -#define WMIX_CustomVolume 0x10 - -#define MAXCHANNELS 16 -#define MAXQUEUEDWAVES 100 - -struct GLOBALS; - -struct volume_struct -{ - uint16_t L; - uint16_t R; -}; - - -struct MIXWAVE -{ - PCMWAVEFORMAT pcm; - WAVEHDR wh; - char szWaveFilename[16]; - short wMagic; -}; - -struct MIXPLAYPARAMS -{ - WORD wSize; - HANDLE hMixSession; - int iChannel; - MIXWAVE* lpMixWave; - HWND hWndNotify; - DWORD dwFlags; - WORD wLoops; - volume_struct Volume; -}; - -struct CHANNELNODE -{ - CHANNELNODE* next; - MIXPLAYPARAMS PlayParams; - MIXWAVE* lpMixWave; - DWORD dwNumSamples; - DWORD dwStartPos; - DWORD dwEndPos; - unsigned char* lpPos; - unsigned char* lpEnd; - volume_struct Volume; -}; - -struct MIXCONFIG -{ - WORD wSize; - DWORD dwFlags; - WORD wChannels; - WORD wSamplingRate; - uint16_t WaveBlockCount; - uint16_t WaveBlockLen; - int16_t CmixPtrDefaultFlag; - uint16_t ResetMixDefaultFlag; - uint16_t GoodWavePos; - uint16_t wDeviceID; - uint16_t PauseBlocks; - int16_t ShowDebugDialogs; - HKEY RegistryKey; -}; - -struct XWAVEHDR -{ - WAVEHDR wh; - BOOL fAvailable; - DWORD dwWavePos; - GLOBALS* g; - struct XWAVEHDR* QNext; -}; - -struct PLAYQUEUE -{ - XWAVEHDR* first; - XWAVEHDR* last; -}; - -struct GLOBALS -{ - WORD wMagic1; - int16_t unknown0; - HWND hWndApp; - int unknown2; - HWAVEOUT hWaveOut; - int fActive; - int SettingsDialogActiveFlag; - unsigned int wDeviceID; - char szDevicePName[96]; - WAVEOUTCAPSA WaveoutCaps; - volume_struct DefaultVolume; - volume_struct ChannelVolume[MAXCHANNELS]; - CHANNELNODE* aChannel[MAXCHANNELS]; - int iChannels; - DWORD MRUChannel[MAXCHANNELS]; - DWORD dwMRU; - PCMWAVEFORMAT PCM; - DWORD dwWaveBlockLen; - int WaveBlockCount; - int PauseBlocks; - XWAVEHDR** WaveBlockArray; - DWORD dwCurrentSample; - DWORD dwBaseTime; - int fGoodGetPos; - DWORD dwWaveOutPos; - void (*CmixPtr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume, int iNumWaves, - uint16_t length); - int (* pfnRemix)(DWORD, CHANNELNODE*); - DWORD (* pfnSampleAdjust)(DWORD, DWORD); - CHANNELNODE* pWaitList; - int16_t wMagic2; - int16_t unknown112; -}; - -struct dialog_template -{ - DLGTEMPLATE Dialog; - WORD menu; - WORD windowClass; - WCHAR Header[1]; -}; - -struct dialog_item_template -{ - DLGITEMTEMPLATE Item; - WORD sysClass; - WORD idClass; - WCHAR Header[1]; -}; - - -class WaveMix -{ -public: - static HANDLE Init(); - static HANDLE ConfigureInit(MIXCONFIG* lpConfig); - static int CloseSession(HANDLE hMixSession); - static int OpenChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags); - static int CloseChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags); - static int FlushChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags); - static MIXWAVE* OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned int dwFlags); - static int FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave); - static int Activate(HANDLE hMixSession, bool fActivate); - static void Pump(); - static int Play(MIXPLAYPARAMS* lpMixPlayParams); - -private: - static GLOBALS* SessionToGlobalDataPtr(HANDLE hMixSession); - static int Startup(HMODULE hModule); - static int SetIniFileName(HMODULE hModule); - static void InitChannelNodes(); - static void InitVolumeTable(); - static void ShowWaveOutDevices(); - static int RemoveInvalidIniNameCharacters(char* lpString); - static int ReadConfigSettings(MIXCONFIG* lpConfig); - static int ReadRegistryForAppSpecificConfigs(MIXCONFIG* lpConfig); - static int ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int defaultValue); - static int DefaultGoodWavePos(unsigned int uDeviceID); - static int DefaultPauseBlocks(int waveBlocks); - static int Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag); - static int GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig); - static unsigned MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos); - static void FreeChannelNode(CHANNELNODE* channel); - static int ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel); - static XWAVEHDR* RemoveFromPlayingQueue(XWAVEHDR* lpXWH); - static void DestroyPlayQueue(); - static void SwapWaveBlocks(); - static XWAVEHDR* GetWaveBlock(); - static int MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks); - static XWAVEHDR* AddToPlayingQueue(XWAVEHDR* lpXWH); - static void MyWaveOutReset(HWAVEOUT hWaveOut); - static void SetWaveOutPosition(unsigned int newPosition); - static DWORD SubFactor(DWORD a1, DWORD a2); - static DWORD AddFactor(DWORD a1, DWORD a2); - static dialog_template* MakeSettingsDlgTemplate(); - static dialog_template* MakeDlgTemplate(size_t* totalSize, unsigned style, int16_t x, int16_t y, int16_t cx, - int16_t cy, - const wchar_t* String); - static dialog_template* AddDlgControl(size_t* totalSize, dialog_template* dlgTemplate, int16_t idClass, - unsigned style, - WORD id, int16_t x, int16_t y, int16_t cx, int16_t cy, - const wchar_t* String); - static void DestroySettingsDlgTemplate(LPCVOID pMem); - static int Settings_OnInitDialog(HWND hWnd, WPARAM wParam, MIXCONFIG* lpMixconfig); - static int Settings_OnCommand(HWND hWnd, int command, LPARAM lParam, int wParam); - static int ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength); - static const char* GetOperatingSystemPrefix(); - static unsigned int FigureOutDMABufferSize(unsigned int waveBlockLen, PCMWAVEFORMAT* pcm); - static int NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel); - static void SaveConfigSettings(unsigned dwFlags); - static void ShowCurrentSettings(); - static unsigned int GetWaveDevice(); - static void FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks); - static int AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks); - static void ReleaseWaveDevice(GLOBALS* globals); - static HPSTR WaveFormatConvert(PCMWAVEFORMAT* lpOutWF, PCMWAVEFORMAT* lpInWF, HPSTR lpInData, DWORD* dwDataSize); - static HPSTR BitsPerSampleAlign(HPSTR lpInData, WORD nInBPS, WORD nOutBPS, DWORD* dwDataSize); - static HPSTR ChannelAlign(HPSTR lpInData, WORD nInChannels, WORD nOutChannels, WORD nBytesPerSample, - DWORD* dwDataSize); - static HPSTR SamplesPerSecAlign(HPSTR lpInData, DWORD nInSamplesPerSec, DWORD nOutSamplesPerSec, - WORD nBytesPerSample, WORD nChannels, DWORD* dwDataSize); - static void AvgSample(HPSTR lpOutData, HPSTR lpInData, unsigned nSkip, int nBytesPerSample, int nChannels); - static void RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nBytesPerSample, int nChannels); - static bool IsValidLPMIXWAVE(MIXWAVE* lpMixWave); - static void FreePlayedBlocks(); - static int HasCurrentOutputFormat(MIXWAVE* lpMixWave); - static CHANNELNODE* GetChannelNode(); - static void ResetWavePosIfNoChannelData(); - static void cmixit(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volumeArr, int iNumWaves, - uint16_t length); - static LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); - static INT_PTR __stdcall SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); - - static int initialized_flag; - static char FileName[276]; - static CHANNELNODE channel_nodes[MAXQUEUEDWAVES]; - static CHANNELNODE* free_channel_nodes; - static unsigned char volume_table[11][256]; - static int debug_flag; - static void (*cmixit_ptr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume, - int iNumWaves, uint16_t length); - static HMODULE HModule; - static GLOBALS *Globals, *GlobalsActive; - static PCMWAVEFORMAT gpFormat; - static int ShowDebugDialogs; - static char string_buffer[256]; - static PLAYQUEUE play_queue; - static CHANNELNODE* play_channel_array[MAXCHANNELS]; - static XWAVEHDR* block_array1[10]; - static XWAVEHDR* block_array2[10]; - static unsigned char* play_data[MAXCHANNELS]; - static volume_struct play_volume[MAXCHANNELS]; - static int play_counter; -}; diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index 56cf46c..8769326 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -639,9 +639,9 @@ void control::pbctrl_bdoor_controller(int key) if (!control_lite198_tag.Component->MessageField) { - if (key <= 'M') + if (key <= 'm') { - if (key == 'M') + if (key == 'm') { v2 = pbctrl_state; if (pbctrl_state == 4 || pbctrl_state == 61 || pbctrl_state == 81 || pbctrl_state == 101) @@ -650,9 +650,9 @@ void control::pbctrl_bdoor_controller(int key) } else { - if (key <= 'D') + if (key <= 'd') { - if (key != 'D') + if (key != 'd') { if (key == ' ') { @@ -665,11 +665,11 @@ void control::pbctrl_bdoor_controller(int key) } if (key != '1') { - if (key != 'A') + if (key != 'a') { - if (key != 'B') + if (key != 'b') { - if (key == 'C') + if (key == 'c') { if (!pbctrl_state) { @@ -704,17 +704,17 @@ void control::pbctrl_bdoor_controller(int key) ++pbctrl_state; return; } - if (key != 'E') + if (key != 'e') { switch (key) { - case 'G': + case 'g': v1 = pbctrl_state != 0 ? 0 : 101; break; - case 'H': + case 'h': v1 = pbctrl_state != 0 ? 0 : 21; break; - case 'I': + case 'i': v2 = pbctrl_state; if (pbctrl_state == 1 || pbctrl_state == 10) goto LABEL_87; @@ -732,9 +732,9 @@ void control::pbctrl_bdoor_controller(int key) } goto LABEL_86; } - if (key <= 'S') + if (key <= 's') { - if (key == 'S') + if (key == 's') { v2 = pbctrl_state; if (pbctrl_state == 12 || pbctrl_state == 29) @@ -743,13 +743,13 @@ void control::pbctrl_bdoor_controller(int key) } else { - if (key != 'N') + if (key != 'n') { - if (key != 'O') + if (key != 'o') { - if (key != 'Q') + if (key != 'q') { - if (key == 'R') + if (key == 'r') { if (!pbctrl_state) { @@ -789,7 +789,7 @@ void control::pbctrl_bdoor_controller(int key) } switch (key) { - case 'T': + case 't': v2 = pbctrl_state; if (pbctrl_state != 30) { @@ -800,14 +800,14 @@ void control::pbctrl_bdoor_controller(int key) } pb::cheat_mode = 1; break; - case 'U': + case 'u': if (pbctrl_state == 41) { pbctrl_state = 42; return; } goto LABEL_77; - case 'X': + case 'x': if (pbctrl_state == 63) { table_add_extra_ball(2.0); diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index 3779003..5349ee0 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -66,7 +66,7 @@ void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HME fullscrn_flag1 = 0; window_size_changed(); - assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size"); + //assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size"); } void fullscrn::shutdown() diff --git a/SpaceCadetPinball/gdrv.cpp b/SpaceCadetPinball/gdrv.cpp index 72acb48..7c9b22a 100644 --- a/SpaceCadetPinball/gdrv.cpp +++ b/SpaceCadetPinball/gdrv.cpp @@ -7,8 +7,7 @@ #include "winmain.h" HPALETTE gdrv::palette_handle = nullptr; -HINSTANCE gdrv::hinst; -HWND gdrv::hwnd; +SDL_Renderer* gdrv::renderer; int gdrv::sequence_handle; HDC gdrv::sequence_hdc; int gdrv::use_wing = 0; @@ -16,13 +15,26 @@ int gdrv::grtext_blue = 0; int gdrv::grtext_green = 0; int gdrv::grtext_red = -1; +HWND hwnd = 0; +SDL_Texture* vScreenTex = nullptr; +char* pixels = nullptr; +int Width, Height; +LOGPALETTEx256 current_palette{}; -int gdrv::init(HINSTANCE hInst, HWND hWnd) +int gdrv::init(SDL_Renderer* render, int width, int height) { - LOGPALETTEx256 current_palette{}; - - hinst = hInst; - hwnd = hWnd; + renderer = render; + vScreenTex = SDL_CreateTexture + ( + renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + width, height + ); + pixels = memory::allocate(width * height * 4); + Width = width; + Height = height; + if (!palette_handle) palette_handle = CreatePalette(¤t_palette); return 0; @@ -32,6 +44,7 @@ int gdrv::uninit() { if (palette_handle) DeleteObject(palette_handle); + memory::free(pixels); return 0; } @@ -185,11 +198,8 @@ int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int si return 0; } - int gdrv::display_palette(PALETTEENTRY* plt) { - LOGPALETTEx256 current_palette{}; - if (palette_handle) DeleteObject(palette_handle); palette_handle = CreatePalette(¤t_palette); @@ -212,9 +222,9 @@ int gdrv::display_palette(PALETTEENTRY* plt) { if (plt) { - pltDst->peRed = pltSrc->peBlue; + pltDst->peRed = pltSrc->peRed; pltDst->peGreen = pltSrc->peGreen; - pltDst->peBlue = pltSrc->peRed; + pltDst->peBlue = pltSrc->peBlue; } pltDst->peFlags = 4; pltSrc++; @@ -426,7 +436,7 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int { /*Scaled partial updates may leave 1px border artifacts around update area. * Pad update area to compensate.*/ - const int pad = 1, padX2 = pad * 2; + /*const int pad = 1, padX2 = pad * 2; if (fullscrn::ScaleX > 1 && xSrc > pad && xSrc + pad < bmp->Width) { xSrc -= pad; @@ -443,7 +453,7 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight += padX2; } - return StretchDIBits( + StretchDIBits( hdc, static_cast(round(xDest * fullscrn::ScaleX + fullscrn::OffsetX)), static_cast(round(yDest * fullscrn::ScaleY + fullscrn::OffsetY)), @@ -456,5 +466,60 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int bmp->BmpBufPtr1, bmp->Dib, iUsage, - rop); + rop);*/ + + //auto srcPtr = reinterpret_cast(bmp->BmpBufPtr1); + //auto dstPtr = reinterpret_cast(pixels); + //for (int y = Height; y > 0; --y) + //{ + // for (int x = Width; x > 0; --x) + // *dstPtr++ = *(uint32_t*)¤t_palette.palPalEntry[*srcPtr++]; + + // //srcPtr += srcBmp->Stride - width; + // //dstPtr += dstBmp->Stride - width; + //} + + // Clamp out of bounds rectangles + ySrc = max(0, min(ySrc, bmp->Height)); + xSrc = max(0, min(xSrc, bmp->Height)); + if (ySrc + SrcHeight > Height) + SrcHeight = Height - ySrc; + if (xSrc + SrcWidth > Width) + SrcWidth = Width - xSrc; + + auto srcPtr = reinterpret_cast(&bmp->BmpBufPtr1[bmp->Stride * (ySrc)+xSrc]); + auto dstPtr = &reinterpret_cast(pixels)[Width * (ySrc)+xSrc]; + for (int y = SrcHeight; y > 0; --y) + { + for (int x = SrcWidth; x > 0; --x) + { + if ((char*)dstPtr >= (pixels + Width * Height * 4) || (char*)srcPtr >= (bmp->BmpBufPtr1 + bmp->Stride * bmp->Width)) + { + dstPtr = dstPtr; + } + + *dstPtr++ = *(uint32_t*)¤t_palette.palPalEntry[*srcPtr++]; + } + + srcPtr += bmp->Stride - SrcWidth; + dstPtr += Width - SrcWidth; + } + + unsigned char* lockedPixels = nullptr; + int pitch = 0; + SDL_LockTexture + ( + vScreenTex, + nullptr, + reinterpret_cast(&lockedPixels), + &pitch + ); + std::memcpy(lockedPixels, pixels, Width * Height * 4); + SDL_UnlockTexture(vScreenTex); + + SDL_Rect dstRect + { xDest,yDest,Width,Height }; + SDL_RenderCopyEx(renderer, vScreenTex, nullptr, nullptr, 0, 0, SDL_FLIP_VERTICAL); + + return 0; } diff --git a/SpaceCadetPinball/gdrv.h b/SpaceCadetPinball/gdrv.h index 6a5e1cc..b6db59d 100644 --- a/SpaceCadetPinball/gdrv.h +++ b/SpaceCadetPinball/gdrv.h @@ -42,7 +42,7 @@ public: static HDC sequence_hdc; static int use_wing; - static int init(HINSTANCE hInst, HWND hWnd); + static int init(SDL_Renderer* renderer, int width, int height); static int uninit(); static void get_focus(); static BITMAPINFO* DibCreate(int16_t bpp, int width, int height); @@ -68,8 +68,7 @@ public: private: /*COLORONCOLOR or HALFTONE*/ static const int stretchMode = COLORONCOLOR; - static HWND hwnd; - static HINSTANCE hinst; + static SDL_Renderer* renderer; static int grtext_blue; static int grtext_green; static int grtext_red; diff --git a/SpaceCadetPinball/high_score.cpp b/SpaceCadetPinball/high_score.cpp index 2e59385..60fbbff 100644 --- a/SpaceCadetPinball/high_score.cpp +++ b/SpaceCadetPinball/high_score.cpp @@ -177,9 +177,9 @@ void high_score::show_and_set_high_score_dialog(high_score_struct* table, int sc dlg_hst = table; dlg_enter_name = 1; default_name = defaultName; - while (DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0)) + /*while (DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0)) { - } + }*/ } INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index 5447bbc..4d31e21 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -320,7 +320,7 @@ float loader::play_sound(int soundIndex) { if (soundIndex <= 0) return 0.0; - Sound::PlaySound(sound_list[soundIndex].WavePtr, 0, 7, WMIX_HIPRIORITY | WMIX_CLEARQUEUE, 0); + Sound::PlaySound(sound_list[soundIndex].WavePtr, 0, 7, 0, 0); return sound_list[soundIndex].Duration; } diff --git a/SpaceCadetPinball/loader.h b/SpaceCadetPinball/loader.h index 0e2ba9a..a3c5d41 100644 --- a/SpaceCadetPinball/loader.h +++ b/SpaceCadetPinball/loader.h @@ -1,7 +1,6 @@ #pragma once #include "gdrv.h" #include "maths.h" -#include "WaveMix.h" #include "zdrv.h" @@ -15,7 +14,7 @@ struct errorMsg struct soundListStruct { - MIXWAVE* WavePtr; + Mix_Chunk* WavePtr; int GroupIndex; int Loaded; float Duration; diff --git a/SpaceCadetPinball/midi.cpp b/SpaceCadetPinball/midi.cpp index 92f3e1a..8a559ba 100644 --- a/SpaceCadetPinball/midi.cpp +++ b/SpaceCadetPinball/midi.cpp @@ -5,10 +5,7 @@ #include "pb.h" #include "pinball.h" -tagMCI_OPEN_PARMSA midi::mci_open_info; -char midi::midi_file_name[28]; -HWND midi::midi_notify_hwnd; -int midi::midi_seq1_open, midi::midi_seq1_playing; +Mix_Music* midi::currentMidi; MCIERROR midi::play_pb_theme(int flag) { @@ -17,17 +14,11 @@ MCIERROR midi::play_pb_theme(int flag) return play_ft(track1); } - MCI_PLAY_PARMS playParams; MCIERROR result = 0; - music_stop(); - playParams.dwFrom = 0; - playParams.dwCallback = (DWORD_PTR)midi_notify_hwnd; - if (!flag && midi_seq1_open) - { - result = mciSendCommandA(mci_open_info.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD_PTR)&playParams); - midi_seq1_playing = result == 0; - } + if (currentMidi) + result = Mix_PlayMusic(currentMidi, -1); + return result; } @@ -37,11 +28,8 @@ MCIERROR midi::music_stop() { return stop_ft(); } - - MCIERROR result = 0; - if (midi_seq1_playing) - result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0); - return result; + + return Mix_HaltMusic(); } int midi::music_init(HWND hwnd) @@ -50,15 +38,9 @@ int midi::music_init(HWND hwnd) { return music_init_ft(hwnd); } - - mci_open_info.wDeviceID = 0; - midi_notify_hwnd = hwnd; - lstrcpyA(midi_file_name, pinball::get_rc_string(156, 0)); - mci_open_info.lpstrElementName = midi_file_name; - mci_open_info.lpstrDeviceType = nullptr; - auto result = mciSendCommandA(0, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_NOTIFY_SUPERSEDED, (DWORD_PTR)&mci_open_info); - midi_seq1_open = result == 0; - return midi_seq1_open; + + currentMidi = Mix_LoadMUS(pinball::get_rc_string(156, 0)); + return currentMidi != nullptr; } MCIERROR midi::restart_midi_seq(LPARAM param) @@ -68,13 +50,11 @@ MCIERROR midi::restart_midi_seq(LPARAM param) return play_ft(active_track); } - MCI_PLAY_PARMS playParams; MCIERROR result = 0; + music_stop(); + if (currentMidi) + result = Mix_PlayMusic(currentMidi, -1); - playParams.dwFrom = 0; - playParams.dwCallback = (DWORD_PTR)midi_notify_hwnd; - if (midi_seq1_playing) - result = mciSendCommandA(mci_open_info.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD_PTR)&playParams); return result; } @@ -86,9 +66,7 @@ void midi::music_shutdown() return; } - if (midi_seq1_open) - mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0); - midi_seq1_open = 0; + Mix_FreeMusic(currentMidi); } @@ -98,7 +76,6 @@ int midi::some_flag1; int midi::music_init_ft(HWND hwnd) { - midi_notify_hwnd = hwnd; active_track = nullptr; TrackList = new objlist_class(0, 1); @@ -423,7 +400,7 @@ int midi::stream_open(midi_struct* midi, char flags) if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) return 6; - UINT puDeviceID = -1; + /*UINT puDeviceID = -1; auto steamOpenedFg = !midi->StreamHandle; MIDIPROPTIMEDIV propdata{8, midi->DwTimeFormat}; if (steamOpenedFg && @@ -463,15 +440,15 @@ int midi::stream_open(midi_struct* midi, char flags) { if (midi->StreamHandle) stream_close(midi); - } + }*/ return returnCode; } int midi::stream_close(midi_struct* midi) { - int returnCode; + int returnCode = 0; - if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) + /*if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) return 6; if (!midi->StreamHandle) return 7; @@ -493,7 +470,7 @@ int midi::stream_close(midi_struct* midi) returnCode = 0; midi->StreamHandle = nullptr; midi->SomeFlag2 = 0; - } + }*/ return returnCode; } @@ -503,8 +480,8 @@ void midi::midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PT { auto mhdr = reinterpret_cast(dwParam1); auto midi = reinterpret_cast(mhdr->dwUser); - if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut( + /*if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut( midi->StreamHandle, mhdr, sizeof(MIDIHDR))) - --midi->PreparedBlocksCount; + --midi->PreparedBlocksCount;*/ } } diff --git a/SpaceCadetPinball/midi.h b/SpaceCadetPinball/midi.h index cecca49..5770eb3 100644 --- a/SpaceCadetPinball/midi.h +++ b/SpaceCadetPinball/midi.h @@ -57,11 +57,8 @@ public: static int music_init(HWND hwnd); static MCIERROR restart_midi_seq(LPARAM param); static void music_shutdown(); -private: - static tagMCI_OPEN_PARMSA mci_open_info; - static char midi_file_name[28]; - static HWND midi_notify_hwnd; - static int midi_seq1_open, midi_seq1_playing; +private: + static Mix_Music* currentMidi; static objlist_class* TrackList; static midi_struct *track1, *track2, *track3, *active_track, *active_track2; diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 45c77fe..8ac931a 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -76,18 +76,18 @@ void options::init(HMENU menuHandle) Options.FullScreen = 0; Options.Average = 5; Options.PriorityAdj = 2; - Options.LeftFlipperKeyDft = 90; - Options.RightFlipperKeyDft = 191; - Options.PlungerKeyDft = 32; - Options.LeftTableBumpKeyDft = 88; - Options.RightTableBumpKeyDft = 190; - Options.BottomTableBumpKeyDft = 38; - pinball::get_rc_int(159, &Options.LeftFlipperKeyDft); + Options.LeftFlipperKeyDft = SDLK_z; + Options.RightFlipperKeyDft = SDLK_SLASH; + Options.PlungerKeyDft = SDLK_SPACE; + Options.LeftTableBumpKeyDft = SDLK_x; + Options.RightTableBumpKeyDft = SDLK_GREATER; + Options.BottomTableBumpKeyDft = SDLK_UP; + /*pinball::get_rc_int(159, &Options.LeftFlipperKeyDft); pinball::get_rc_int(160, &Options.RightFlipperKeyDft); pinball::get_rc_int(161, &Options.PlungerKeyDft); pinball::get_rc_int(162, &Options.LeftTableBumpKeyDft); pinball::get_rc_int(163, &Options.RightTableBumpKeyDft); - pinball::get_rc_int(164, &Options.BottomTableBumpKeyDft); + pinball::get_rc_int(164, &Options.BottomTableBumpKeyDft);*/ Options.LeftFlipperKey = Options.LeftFlipperKeyDft; Options.RightFlipperKey = Options.RightFlipperKeyDft; Options.PlungerKey = Options.PlungerKeyDft; @@ -95,7 +95,7 @@ void options::init(HMENU menuHandle) Options.RightTableBumpKey = Options.RightTableBumpKeyDft; Options.Players = 1; Options.BottomTableBumpKey = Options.BottomTableBumpKeyDft; - Options.Sounds = get_int(nullptr, "Sounds", Options.Sounds); + /*Options.Sounds = get_int(nullptr, "Sounds", Options.Sounds); Options.Music = get_int(nullptr, "Music", Options.Music); Options.Average = get_int(nullptr, "Average", Options.Average); Options.FullScreen = get_int(nullptr, "FullScreen", Options.FullScreen); @@ -107,7 +107,7 @@ void options::init(HMENU menuHandle) Options.LeftTableBumpKey = get_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey); Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); - Options.UniformScaling = get_int(nullptr, "Uniform scaling", true); + Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);*/ menu_check(Menu1_Sounds, Options.Sounds); Sound::Enable(0, 7, Options.Sounds); menu_check(Menu1_Music, Options.Music); @@ -137,7 +137,7 @@ void options::init(HMENU menuHandle) void options::uninit() { - set_int(nullptr, "Sounds", Options.Sounds); + /*set_int(nullptr, "Sounds", Options.Sounds); set_int(nullptr, "Music", Options.Music); set_int(nullptr, "FullScreen", Options.FullScreen); set_int(nullptr, "Players", Options.Players); @@ -148,7 +148,7 @@ void options::uninit() set_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); set_int(nullptr, "Screen Resolution", Options.Resolution); - set_int(nullptr, "Uniform scaling", Options.UniformScaling); + set_int(nullptr, "Uniform scaling", Options.UniformScaling);*/ } void options::path_init(LPCSTR regPath) diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index efd2594..8823f46 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -17,6 +17,7 @@ #include "timer.h" #include "winmain.h" #include "resource.h" +#include "Sound.h" #include "TBall.h" #include "TDemo.h" #include "TEdgeSegment.h" @@ -32,7 +33,7 @@ high_score_struct pb::highscore_table[5]; bool pb::FullTiltMode = false; -int pb::init() +int pb::init(SDL_Renderer* render) { float projMat[12], zMin = 0, zScaler = 0; CHAR datFileName[300]; @@ -74,6 +75,7 @@ int pb::init() zScaler = cameraInfo[2]; } + gdrv::init(render, resInfo->TableWidth, resInfo->TableHeight); render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight); gdrv::copy_bitmap( &render::vscreen, @@ -332,6 +334,7 @@ void pb::pause_continue() MainTable->Message(1008, time_now); pinball::InfoTextBox->Display(pinball::get_rc_string(22, 0), -1.0); midi::music_stop(); + Sound::Deactivate(); } else { @@ -355,6 +358,7 @@ void pb::pause_continue() } if (options::Options.Music && !winmain::single_step) midi::play_pb_theme(0); + Sound::Activate(); } } diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index 6aafc64..b153436 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -16,7 +16,7 @@ public: static high_score_struct highscore_table[5]; static bool FullTiltMode; - static int init(); + static int init(SDL_Renderer* render); static int uninit(); static void reset_table(); static void firsttime_setup(); diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 3cee88d..0cba5f9 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -18,8 +18,15 @@ #include #include #include /*For control template*/ +#include +#include +#include //#include +#define SDL_MAIN_HANDLED +#include "SDL.h" +#include + /*Use (void) to silent unused warnings.*/ #define assertm(exp, msg) assert(((void)msg, exp)) diff --git a/SpaceCadetPinball/pinball.cpp b/SpaceCadetPinball/pinball.cpp index c2ffb5a..b5abdc8 100644 --- a/SpaceCadetPinball/pinball.cpp +++ b/SpaceCadetPinball/pinball.cpp @@ -3,6 +3,220 @@ #include "memory.h" #include "winmain.h" +// Todo: load translations from file +std::map rc_strings +{ + {0, "Replay Awarded"}, + {1, "Ball Locked"}, + {2, "Center Post\n%ld"}, + {3, "Bonus Awarded\n%ld"}, + {4, "Bonus Activated"}, + {5, "Weapons Upgraded"}, + {6, "Engine Upgraded"}, + {7, "Bonus up 1 Million"}, + {8, "Extra Ball Available\n%ld"}, + {9, "Extra Ball"}, + {10, "Reflex Shot Award\n%ld"}, + {11, "Final Battle Won"}, + {12, "Hyperspace Bonus\n%ld"}, + {13, "Hyperspace Bonus Available"}, + {14, "Jackpot Awarded\n%ld"}, + {15, "Jackpot Activated"}, + {16, "Multiball"}, + {17, "Ramp Bonus Awarded"}, + {18, "Light Added"}, + {19, "Ramp Bonus On"}, + {20, "Light Reset Off"}, + {21, "Skill Shot\n%ld"}, + {22, "Game Paused\nF3 to Resume"}, + {23, "Continue Play"}, + {24, "F2 Starts New Game"}, + {25, "Careful..."}, + {26, "Player 1"}, + {27, "Player 2"}, + {28, "Player 3"}, + {29, "Player 4"}, + {30, "Demo\nPlayer 1"}, + {31, "Demo\nPlayer 2"}, + {32, "Demo\nPlayer 3"}, + {33, "Demo\nPlayer 4"}, + {34, "Game Over"}, + {35, "TILT!"}, + {36, "This program requires an 80386 or later CPU."}, + {37, "80386 Required"}, + {38, "3D Pinball for Windows - Space Cadet"}, + { + 39, + "One or more of the player controls is set to the same key,\nfor best performance use unique keys for each control." + }, + {40, "Clear High Scores?"}, + {41, "Confirm"}, + {42, "WAVEMIX.INF is missing - it must be in the pinball directory!"}, + {43, "Warning:"}, + {44, "Ship Re-Fueled"}, + {45, "Gravity Well"}, + {46, "Time Warp Forward"}, + {47, "Time Warp Backward"}, + {48, "Maelstrom!"}, + {49, "Wormhole"}, + {50, "Awaiting Deployment"}, + {51, "Flags Upgraded"}, + {52, "Bonus Hold"}, + {53, "Level One Commation"}, + {54, "Level Two Commation"}, + {55, "Level Three Commation"}, + {56, "Field Multiplier 2x"}, + {57, "Field Multiplier 3x"}, + {58, "Field Multiplier 5x"}, + {59, "Field Multiplier 10x"}, + {60, "Target Practice"}, + {61, "Launch Training"}, + {62, "Re-Entry Training"}, + {63, "Science"}, + {64, "Stray Comet"}, + {65, "Black Hole"}, + {66, "Space Radiation"}, + {67, "Bug Hunt"}, + {68, "Alien Menace"}, + {69, "Rescue"}, + {70, "Satellite Retrieval"}, + {71, "Recon"}, + {72, "Doomsday Machine"}, + {73, "Cosmic Plague"}, + {74, "Secret"}, + {75, "Time Warp"}, + {76, "Maelstrom"}, + {77, "Mission Accepted\n%ld"}, + {78, "Mission Completed\n%ld"}, + {79, "%s Mission Selected"}, + {80, "Black Hole\n%ld"}, + {81, "Gravity Normalized\n%ld"}, + {82, "Gravity Well\n%ld"}, + {83, "Promotion to %s"}, + {84, "Cadet"}, + {85, "Ensign"}, + {86, "Lieutenant"}, + {87, "Captain"}, + {88, "Lt Commander"}, + {89, "Commander"}, + {90, "Commodore"}, + {91, "Admiral"}, + {92, "Fleet Admiral"}, + {93, "Wormhole Opened"}, + {94, "Crash Bonus\n%ld"}, + {95, "Replay Ball"}, + {96, "Re-Deploy"}, + {97, "Player 1 Shoot Again"}, + {98, "Player 2 Shoot Again"}, + {99, "Player 3 Shoot Again"}, + {100, "Player 4 Shoot Again"}, + { + 101, + "This 3D Pinball Table was created for Microsoft by Maxis.\nFor more information call (800)-336-2947\n(US and Canadian customers only).\nCopyright (c) 1995 Maxis." + }, + {102, "3D Pinball Table created for Microsoft by Maxis. Copyright (c) 1995 Maxis."}, + {103, "About 3D Pinball"}, + {104, "Hit Mission Targets To Select Mission"}, + {105, "Re-Fuel Ship"}, + {106, "Launch Ramp To Accept %s Mission"}, + {107, "Attack Bumpers Hits\nLeft: %d"}, + {108, "Target Training Passed"}, + {109, "Mission Aborted"}, + {110, "Launches Left: %d"}, + {111, "Launch Training Passed"}, + {112, "Re-Entries Left: %d"}, + {113, "Re-Entry Training Passed"}, + {114, "Drop Targets\nLeft: %d"}, + {115, "Science Mission Completed"}, + {116, "Warning -- Low Fuel"}, + {117, "Fill Right Hazard Banks"}, + {118, "Hyperspace Launch"}, + {119, "Comet Destroyed"}, + {120, "Enter Wormhole"}, + {121, "Radiation Eliminated"}, + {122, "Upgrade Launch Bumpers"}, + {123, "Enter Black Hole"}, + {124, "Black Hole Eliminated"}, + {125, "Targets\nLeft: %d"}, + {126, "Xenomorphs Destroyed"}, + {127, "Upgrade Flags"}, + {128, "Hyperspace Launch"}, + {129, "Survivors Rescued"}, + {130, "Aliens Repelled"}, + {131, "Hit Fuel Targets"}, + {132, "Remote Attack Bumper Hits\nLeft: %d"}, + {133, "Satellite Repaired"}, + {134, "Lane Passes\nLeft: %d"}, + {135, "Shoot Ball Up Fuel Chute"}, + {136, "Survey Complete"}, + {137, "Out Lane Passes\nLeft: %d"}, + {138, "Doomsday Machine Destroyed"}, + {139, "Roll Flags: %d"}, + {140, "Hit Space Warp Rollover"}, + {141, "Plague Eliminated"}, + {142, "Hit Yellow Wormhole"}, + {143, "Hit Red Wormhole"}, + {144, "Hit Green Wormhole"}, + {145, "Plans Recovered"}, + {146, "Rebound Hits\nLeft: %d"}, + {147, "Hit Hyperspace Chute or Launch Ramp"}, + {148, "Drop Target Hits\nLeft: %d"}, + {149, "Spot Target Hits\nLeft: %d"}, + {150, "Lanes Passes\nLeft: %d"}, + {151, "Shoot Ball Up Fuel Chute"}, + {152, "Hit Launch Ramp"}, + {153, "Hit Flags"}, + {154, "Hit Worm Hole"}, + {155, "Hyperspace Chute to Maelstrom"}, + {156, "pinball.mid"}, + {158, "1 UseBitmapFont"}, + {159, "90 Left Flipper Key"}, + {160, "191 Right Flipper Key"}, + {161, "32 Plunger Key"}, + {162, "88 Bump Left Key"}, + {163, "190 Bump Right Key"}, + {164, "38 Bump Bottom Key"}, + {165, "Software\\Microsoft\\Plus!\\Pinball"}, + {166, "SpaceCadet"}, + {167, "1c7c22a0-9576-11ce-bf80-444553540000"}, + {168, "PINBALL.DAT"}, + {169, "Space Cadet"}, + {170, "Error:"}, + {171, "Unable to find other tables."}, + {172, "3D Pinball\nSpace Cadet"}, + {173, "Promotion to %s"}, + {174, "Demotion to %s"}, + {175, "Upgrade Attack Bumpers"}, + {176, "Fill Left Hazard Banks"}, + {177, "HIGH SCORE"}, + {178, "pinball.chm"}, + {179, "Not enough memory to run 3D Pinball."}, + {180, "Player 1's Score\n%ld"}, + {181, "Player 2's Score\n%ld"}, + {182, "Player 3's Score\n%ld"}, + {183, "Player 4's Score\n%ld"}, + {184, "High Score 1\n%ld"}, + {185, "High Score 2\n%ld"}, + {186, "High Score 3\n%ld"}, + {187, "High Score 4\n%ld"}, + {188, "High Score 5\n%ld"}, + {189, "255 255 255 (R G B default font color)"}, + {2030, "Use &Maximum Resolution (640 x 480)"}, + {2031, "Use &Maximum Resolution (800 x 600)"}, + {2032, "Use &Maximum Resolution (1024 x 768)"} +}; + +int LoadStringL(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax) +{ + auto str = rc_strings.find(uID); + if (str == rc_strings.end()) + { + return 0; + } + + lstrcpyA(lpBuffer, str->second); + return 1; +} int pinball::quickFlag = 0; TTextBox* pinball::InfoTextBox; @@ -15,7 +229,7 @@ int pinball::RightShift = -1; char* pinball::get_rc_string(int uID, int a2) { char* result = &getRcBuffer[256 * rc_string_slot]; - if (!LoadStringA(winmain::hinst, uID, &getRcBuffer[256 * rc_string_slot], 255)) + if (!LoadStringL(winmain::hinst, uID, &getRcBuffer[256 * rc_string_slot], 255)) *result = 0; if (++rc_string_slot >= 6) rc_string_slot = 0; @@ -25,7 +239,7 @@ char* pinball::get_rc_string(int uID, int a2) int pinball::get_rc_int(int uID, int* dst) { char buffer[255]; - int result = LoadStringA(winmain::hinst, uID, buffer, 255); + int result = LoadStringL(winmain::hinst, uID, buffer, 255); if (!result) return result; *dst = atoi(buffer); diff --git a/SpaceCadetPinball/score.cpp b/SpaceCadetPinball/score.cpp index 0a1a072..bbfb1f9 100644 --- a/SpaceCadetPinball/score.cpp +++ b/SpaceCadetPinball/score.cpp @@ -10,6 +10,12 @@ #include "TDrain.h" #include "winmain.h" +// Todo: load font from file +const uint8_t PB_MSGFT_bin[] +{ + 0x02, 0x00, 0x0F, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x05, 0x07, 0x0C, 0x08, 0x13, 0x11, 0x03, 0x07, 0x07, 0x0A, 0x0B, 0x05, 0x0B, 0x05, 0x08, 0x0C, 0x07, 0x0B, 0x0B, 0x0D, 0x0B, 0x0C, 0x0B, 0x0C, 0x0C, 0x05, 0x06, 0x0C, 0x0C, 0x0C, 0x0B, 0x10, 0x0C, 0x0C, 0x0A, 0x0E, 0x0A, 0x09, 0x11, 0x0C, 0x04, 0x08, 0x0D, 0x09, 0x12, 0x0D, 0x11, 0x0C, 0x12, 0x0C, 0x0B, 0x0A, 0x0C, 0x0D, 0x12, 0x0C, 0x0A, 0x0B, 0x06, 0x0A, 0x06, 0x08, 0x02, 0x05, 0x0D, 0x0D, 0x07, 0x0D, 0x0C, 0x07, 0x0C, 0x0A, 0x04, 0x06, 0x0A, 0x04, 0x10, 0x0A, 0x0C, 0x0D, 0x0D, 0x07, 0x08, 0x06, 0x0A, 0x0B, 0x10, 0x0A, 0x0A, 0x0A, 0x08, 0x02, 0x07, 0x0B, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x00, 0x30, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x64, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x30, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x00, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x0A, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x0A, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x00, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x30, 0x37, 0x64, 0x30, 0x00, 0x00, 0x07, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x64, 0x30, 0x64, 0x30, 0x64, 0x30, 0x00, 0x00, 0x64, 0x30, 0x37, 0x30, 0x00, 0x00, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x64, 0x30, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + score_msg_font_type* score::msg_fontp; int score::init() @@ -68,21 +74,14 @@ void score::load_msg_font(LPCSTR lpName) void score::load_msg_font_3DPB(LPCSTR lpName) { - auto resHandle = FindResourceA(winmain::hinst, lpName, RT_RCDATA); - if (!resHandle) + if (strcmp(lpName, "pbmsg_ft") != 0) return; - - auto resGlobal = LoadResource(winmain::hinst, resHandle); - if (!resGlobal) - return; - - auto rcData = static_cast(LockResource(resGlobal)); + auto rcData = reinterpret_cast(PB_MSGFT_bin); auto fontp = memory::allocate(); msg_fontp = fontp; if (!fontp) { - FreeResource(resGlobal); return; } memset(fontp->Chars, 0, sizeof fontp->Chars); @@ -102,7 +101,6 @@ void score::load_msg_font_3DPB(LPCSTR lpName) { memory::free(msg_fontp); msg_fontp = nullptr; - FreeResource(resGlobal); return; } @@ -148,7 +146,6 @@ void score::load_msg_font_3DPB(LPCSTR lpName) memory::free(tmpCharBur); if (charInd != 128) unload_msg_font(); - FreeResource(resGlobal); } void score::load_msg_font_FT(LPCSTR lpName) diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index 5e9544e..0d74cad 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -11,9 +11,12 @@ #include "resource.h" #include "splash.h" +const double TargetFps = 60, TargetFrameTime = 1000 / TargetFps; + HINSTANCE winmain::hinst = nullptr; HWND winmain::hwnd_frame = nullptr; HCURSOR winmain::mouse_hsave; +SDL_Window* winmain::MainWindow = nullptr; int winmain::return_value = 0; int winmain::bQuit = 0; @@ -36,6 +39,15 @@ gdrv_bitmap8 winmain::gfr_display{}; char winmain::DatFileName[300]{}; +uint32_t timeGetTimeAlt() +{ + auto now = std::chrono::high_resolution_clock::now(); + auto duration = now.time_since_epoch(); + auto millis = std::chrono::duration_cast(duration).count(); + return static_cast(millis); +} + + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { return winmain::WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd); @@ -46,75 +58,20 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi memory::init(memalloc_failure); ++memory::critical_allocation; auto optionsRegPath = pinball::get_rc_string(165, 0); - options::path_init(optionsRegPath); - auto regSpaceCadet = pinball::get_rc_string(166, 0); - - if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1) - { - auto tmpBuf = memory::allocate(0x1F4u); - if (!tmpBuf) - { - options::path_uninit(); - return 0; - } - - options::set_int(regSpaceCadet, "Table Version", 1u); - GetModuleFileNameA(hinst, tmpBuf, 0x1F4u); - options::set_string(regSpaceCadet, "Table Exe", tmpBuf); - options::set_string(regSpaceCadet, "Table Name", pinball::get_rc_string(169, 0)); - options::set_string(nullptr, "Last Table Played", regSpaceCadet); - memory::free(static_cast(tmpBuf)); - tmpBuf = memory::allocate(0x1F4u); - if (tmpBuf) - { - auto tmpBuf2 = memory::allocate(0x1F4u); - if (tmpBuf2) - { - char Buffer[40]; - bool setOption = false; - for (int i = 0; i < 32700; ++i) - { - sprintf_s(Buffer, "Table%d", i); - options::get_string(nullptr, Buffer, tmpBuf, "", 500); - if (!*tmpBuf) - break; - options::get_string(tmpBuf, "Table Name", tmpBuf2, "", 500); - if (!lstrcmpA(tmpBuf2, pinball::get_rc_string(169, 0))) - { - setOption = false; - break; - } - if (!*tmpBuf2) - break; - } - if (setOption) - options::set_string(nullptr, Buffer, regSpaceCadet); - memory::free(tmpBuf2); - } - memory::free(tmpBuf); - } - } - else - { - auto tmpBuf = memory::allocate(0x1F4u); - if (!tmpBuf) - { - options::path_uninit(); - return 0; - } - options::get_string(regSpaceCadet, "Shell Exe", tmpBuf, "", 500); - auto execRes = WinExec(tmpBuf, 5u); - memory::free(tmpBuf); - if (execRes >= 32) - { - options::path_uninit(); - return 0; - } - } + options::path_init(optionsRegPath); --memory::critical_allocation; + // SDL init + SDL_SetMainReady(); + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not initialize SDL2", SDL_GetError(), nullptr); + return 1; + } + pinball::quickFlag = strstr(lpCmdLine, "-quick") != nullptr; hinst = hInstance; + auto regSpaceCadet = pinball::get_rc_string(166, 0); options::get_string(regSpaceCadet, "Pinball Data", DatFileName, pinball::get_rc_string(168, 0), 300); /*Check for full tilt .dat file and switch to it automatically*/ @@ -141,38 +98,66 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi if (check_expiration_date()) return 0; - INITCOMMONCONTROLSEX picce; - picce.dwSize = 8; - picce.dwICC = 5885; - InitCommonControlsEx(&picce); - - WNDCLASSEXA wndClass{}; - wndClass.cbSize = sizeof wndClass; - wndClass.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT; - wndClass.lpfnWndProc = message_handler; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hInstance = hInstance; - wndClass.hIcon = LoadIconA(hInstance, "ICON_1"); - wndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)16; - wndClass.lpszMenuName = "MENU_1"; - wndClass.lpszClassName = windowClass; auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap"); - RegisterClassExA(&wndClass); - pinball::FindShiftKeys(); options::init_resolution(); - char windowName[40]; - lstrcpyA(windowName, pinball::get_rc_string(38, 0)); - windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance, - nullptr); - hwnd_frame = windowHandle; - if (!windowHandle) + // SDL window + SDL_Window* window = SDL_CreateWindow + ( + pinball::get_rc_string(38, 0), + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + 800, 600, + SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE + ); + MainWindow = window; + if (!window) { - PostQuitMessage(0); - return 0; + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not create window", SDL_GetError(), nullptr); + return 1; + } + + SDL_Renderer* renderer = SDL_CreateRenderer + ( + window, + -1, + SDL_RENDERER_ACCELERATED + ); + if (!renderer) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not create renderer", SDL_GetError(), window); + return 1; + } + + // PB init from message handler + { + RECT rect{}; + ++memory::critical_allocation; + + auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT)); + + auto voiceCount = options::get_int(nullptr, "Voices", 8); + if (!Sound::Init(voiceCount)) + options::menu_set(Menu1_Sounds, 0); + Sound::Activate(); + + if (!pinball::quickFlag && !midi::music_init((HWND)window)) + options::menu_set(Menu1_Music, 0); + + if (pb::init(renderer)) + _exit(0); + SetCursor(prevCursor); + auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1); + auto menuHandle = GetMenu((HWND)window); + + GetWindowRect(GetDesktopWindow(), &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + pb::window_size(&width, &height); + fullscrn::init(width, height, options::Options.FullScreen, (HWND)window, menuHandle, + changeDisplayFg); + + --memory::critical_allocation; } auto menuHandle = GetMenu(windowHandle); @@ -186,9 +171,8 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi options::menu_check(Menu1_Full_Screen, 1); } - ShowWindow(hwnd_frame, nShowCmd); + SDL_ShowWindow(window); fullscrn::set_screen_mode(options::Options.FullScreen); - UpdateWindow(hwnd_frame); if (splash) { @@ -197,9 +181,9 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi } pinball::adjust_priority(options::Options.PriorityAdj); - const auto startTime = timeGetTime(); + const auto startTime = timeGetTimeAlt(); MSG wndMessage{}; - while (timeGetTime() >= startTime && timeGetTime() - startTime < 0) // Don't wait for now, was 2000 + while (timeGetTimeAlt() >= startTime && timeGetTimeAlt() - startTime < 0) // Don't wait for now, was 2000 PeekMessageA(&wndMessage, hwnd_frame, 0, 0, 1u); if (strstr(lpCmdLine, "-demo")) @@ -207,21 +191,27 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi else pb::replay_level(0); - DWORD someTimeCounter = 300u, prevTime = 0u; - then = timeGetTime(); + DWORD updateCounter = 300u, frameCounter = 0, prevTime = 0u; + then = timeGetTimeAlt(); + + double sdlTimerResMs = 1000.0 / static_cast(SDL_GetPerformanceFrequency()); + auto frameStart = static_cast(SDL_GetPerformanceCounter()); while (true) - { - if (!someTimeCounter) + { + if (!updateCounter) { - someTimeCounter = 300; + updateCounter = 300; if (DispFrameRate) { - auto curTime = timeGetTime(); + auto curTime = timeGetTimeAlt(); if (prevTime) { char buf[60]; - sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / (static_cast(curTime - prevTime) * 0.001f)); - SetWindowTextA(hwnd_frame, buf); + auto elapsedSec = static_cast(curTime - prevTime) * 0.001f; + sprintf_s(buf, "Updates/sec = %02.02f Frames/sec = %02.02f ", + 300.0f / elapsedSec, frameCounter / elapsedSec); + SDL_SetWindowTitle(window, buf); + frameCounter = 0; if (DispGRhistory) { @@ -256,8 +246,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi prevTime = 0; } } - - Sound::Idle(); + if (!ProcessWindowMessages() || bQuit) break; @@ -265,22 +254,18 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi { if (mouse_down) { - now = timeGetTime(); + now = timeGetTimeAlt(); if (now - then >= 2) { - /*last_mouse_n is in client coordinates*/ - POINT Point; - GetCursorPos(&Point); - ScreenToClient(hwnd_frame, &Point); - pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y); - Point = POINT{last_mouse_x, last_mouse_y}; - ClientToScreen(hwnd_frame, &Point); - SetCursorPos(Point.x, Point.y); + int x, y; + SDL_GetMouseState(&x, &y); + pb::ballset(last_mouse_x - x, y - last_mouse_y); + SDL_WarpMouseInWindow(window, last_mouse_x, last_mouse_y); } } if (!single_step) { - auto curTime = timeGetTime(); + auto curTime = timeGetTimeAlt(); now = curTime; if (no_time_loss) { @@ -302,10 +287,20 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi { fillChar = -7; } - gdrv::fill_bitmap(&gfr_display, 1, 10, 299 - someTimeCounter, 0, fillChar); + gdrv::fill_bitmap(&gfr_display, 1, 10, 299 - updateCounter, 0, fillChar); } - --someTimeCounter; + --updateCounter; then = now; + + auto frameEnd = static_cast(SDL_GetPerformanceCounter()); + auto elapsedMs = (frameEnd - frameStart) * sdlTimerResMs; + if (elapsedMs >= TargetFrameTime) + { + // Keep track of remainder, limited to one frame time. + frameStart = frameEnd - min(elapsedMs - TargetFrameTime, TargetFrameTime) / sdlTimerResMs; + SDL_RenderPresent(renderer); + frameCounter++; + } } } } @@ -390,17 +385,17 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP ++memory::critical_allocation; auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT)); - gdrv::init(hinst, hWnd); + gdrv::init(nullptr,0,0); auto voiceCount = options::get_int(nullptr, "Voices", 8); - if (!Sound::Init(hinst, voiceCount, nullptr)) + if (!Sound::Init(voiceCount)) options::menu_set(Menu1_Sounds, 0); Sound::Activate(); if (!pinball::quickFlag && !midi::music_init(hWnd)) options::menu_set(Menu1_Music, 0); - if (pb::init()) + if (pb::init(nullptr)) _exit(0); SetCursor(prevCursor); auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1); @@ -725,33 +720,187 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP return DefWindowProcA(hWnd, Msg, wParam, lParam); } +int winmain::event_handler(const SDL_Event* event) +{ + switch (event->type) + { + case SDL_QUIT: + end_pause(); + bQuit = 1; + PostQuitMessage(0); + fullscrn::shutdown(); + return_value = 0; + return 0; + case SDL_KEYUP: + pb::keyup(event->key.keysym.sym); + break; + case SDL_KEYDOWN: + if (!event->key.repeat) + pb::keydown(event->key.keysym.sym); + switch (event->key.keysym.sym) + { + case SDLK_ESCAPE: + if (options::Options.FullScreen) + options::toggle(Menu1_Full_Screen); + SDL_MinimizeWindow(MainWindow); + break; + case SDLK_F1: + help_introduction(hinst, (HWND)MainWindow); + break; + case SDLK_F2: + new_game(); + break; + case SDLK_F3: + pause(); + break; + case SDLK_F4: + options::toggle(Menu1_Full_Screen); + break; + case SDLK_F5: + options::toggle(Menu1_Sounds); + break; + case SDLK_F6: + options::toggle(Menu1_Music); + break; + case SDLK_F8: + if (!single_step) + pause(); + options::keyboard(); + break; + default: + break; + } + + if (!pb::cheat_mode) + break; + + switch (event->key.keysym.sym) + { + case SDLK_h: + DispGRhistory = 1; + break; + case SDLK_y: + SDL_SetWindowTitle(MainWindow, "Pinball"); + DispFrameRate = DispFrameRate == 0; + break; + case SDLK_F1: + pb::frame(10); + break; + case SDLK_F10: + single_step = single_step == 0; + if (single_step == 0) + no_time_loss = 1; + break; + default: + break; + } + break; + case SDL_MOUSEBUTTONDOWN: + switch (event->button.button) + { + case SDL_BUTTON_LEFT: + if (pb::cheat_mode) + { + mouse_down = 1; + last_mouse_x = event->button.x; + last_mouse_y = event->button.y; + SDL_ShowCursor(SDL_DISABLE); + SDL_SetWindowGrab(MainWindow, SDL_TRUE); + } + else + pb::keydown(options::Options.LeftFlipperKey); + break; + case SDL_BUTTON_RIGHT: + if (!pb::cheat_mode) + pb::keydown(options::Options.RightFlipperKey); + break; + case SDL_BUTTON_MIDDLE: + pb::keydown(options::Options.PlungerKey); + break; + default: + break; + } + break; + case SDL_MOUSEBUTTONUP: + switch (event->button.button) + { + case SDL_BUTTON_LEFT: + if (mouse_down) + { + mouse_down = 0; + SDL_ShowCursor(SDL_ENABLE); + SDL_SetWindowGrab(MainWindow, SDL_FALSE); + } + if (!pb::cheat_mode) + pb::keyup(options::Options.LeftFlipperKey); + break; + case SDL_BUTTON_RIGHT: + if (!pb::cheat_mode) + pb::keyup(options::Options.RightFlipperKey); + break; + case SDL_BUTTON_MIDDLE: + pb::keyup(options::Options.PlungerKey); + break; + default: + break; + } + break; + case SDL_WINDOWEVENT: + switch (event->window.event) + { + case SDL_WINDOWEVENT_FOCUS_GAINED: + case SDL_WINDOWEVENT_TAKE_FOCUS: + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_SHOWN: + activated = 1; + Sound::Activate(); + if (options::Options.Music && !single_step) + midi::play_pb_theme(0); + no_time_loss = 1; + pinball::adjust_priority(options::Options.PriorityAdj); + has_focus = 1; + gdrv::get_focus(); + fullscrn::force_redraw(); + pb::paint(); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + case SDL_WINDOWEVENT_HIDDEN: + activated = 0; + fullscrn::activate(0); + options::menu_check(Menu1_Full_Screen, 0); + options::Options.FullScreen = 0; + SetThreadPriority(GetCurrentThread(), 0); + Sound::Deactivate(); + midi::music_stop(); + has_focus = 0; + gdrv::get_focus(); + pb::loose_focus(); + break; + default: ; + } + break; + default: ; + } + + return 1; +} + int winmain::ProcessWindowMessages() { - MSG Msg{}; - + SDL_Event event; if (has_focus && !single_step) { - while (PeekMessageA(&Msg, nullptr, 0, 0, 1u)) + while (SDL_PollEvent(&event)) { - TranslateMessage(&Msg); - DispatchMessageA(&Msg); - if (Msg.message == 18) - { - return_value = static_cast(Msg.wParam); + if (!event_handler(&event)) return 0; - } } + return 1; } - GetMessageA(&Msg, hwnd_frame, 0, 0); - TranslateMessage(&Msg); - DispatchMessageA(&Msg); - if (Msg.message == 18) - { - return_value = static_cast(Msg.wParam); - return 0; - } - return 1; + + SDL_WaitEvent(&event); + return event_handler(&event); } void winmain::memalloc_failure() @@ -842,7 +991,7 @@ void winmain::help_introduction(HINSTANCE a1, HWND a2) options::get_string(pinball::get_rc_string(166, 0), "HelpFile", buf1, buf1, 500); lstrcpyA(buf2, buf1); memory::free(buf1); - HtmlHelpA(GetDesktopWindow(), buf2, 0, 0); + //HtmlHelpA(GetDesktopWindow(), buf2, 0, 0); memory::free(buf2); } else diff --git a/SpaceCadetPinball/winmain.h b/SpaceCadetPinball/winmain.h index ff49949..d054ad3 100644 --- a/SpaceCadetPinball/winmain.h +++ b/SpaceCadetPinball/winmain.h @@ -13,6 +13,7 @@ public: static int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd); static LRESULT CALLBACK message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + static int event_handler(const SDL_Event* event); static void memalloc_failure(); static int ProcessWindowMessages(); static int check_expiration_date(); @@ -31,6 +32,7 @@ private: static gdrv_bitmap8 gfr_display; static HCURSOR mouse_hsave; static bool restart; + static SDL_Window* MainWindow; static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); };