From fbe8630e8647e15536243f4a1b309831c7ccefa1 Mon Sep 17 00:00:00 2001 From: Roman Turchin Date: Mon, 30 Dec 2024 19:17:34 -0500 Subject: [PATCH 01/23] Add build target "web" --- .gitignore | 7 + Makefile.web | 37 +++++ files/web/dist/fheroes2.jpeg | Bin 0 -> 79045 bytes files/web/dist/index.html | 208 +++++++++++++++++++++++++++++ files/web/readme | 14 ++ files/web/sdl2_mixer.py | 126 +++++++++++++++++ src/dist/Makefile | 8 ++ src/dist/Makefile.web | 40 ++++++ src/dist/web/Makefile | 55 ++++++++ src/engine/thread.cpp | 13 +- src/fheroes2/game/game_hotkeys.cpp | 9 ++ src/fheroes2/game/game_io.cpp | 10 +- src/fheroes2/system/settings.cpp | 10 +- 13 files changed, 533 insertions(+), 4 deletions(-) create mode 100644 Makefile.web create mode 100644 files/web/dist/fheroes2.jpeg create mode 100644 files/web/dist/index.html create mode 100644 files/web/readme create mode 100644 files/web/sdl2_mixer.py create mode 100644 src/dist/Makefile.web create mode 100644 src/dist/web/Makefile diff --git a/.gitignore b/.gitignore index af8057fc82b..bddbe0d8d26 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,10 @@ android/app/src/main/assets/files/ # Mac magic folders .DS_Store + +#web build artifacts +*.wasm +*.wasm.map +fheroes2.js +fheroes2.data +src/dist/web/dist/* diff --git a/Makefile.web b/Makefile.web new file mode 100644 index 00000000000..f935cbe2080 --- /dev/null +++ b/Makefile.web @@ -0,0 +1,37 @@ +########################################################################### +# fheroes2: https://github.com/ihhub/fheroes2 # +# Copyright (C) 2021 - 2024 # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +########################################################################### + +# Options: +# +# FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) +# FHEROES2_WITH_DEBUG: build in debug mode +# FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) + +PROJECT_NAME := fheroes2 +PROJECT_VERSION := $(file < version.txt) + +.PHONY: all clean + +all: + $(MAKE) -C src/dist PLATFORM=web + +clean: + $(MAKE) -C src/dist PLATFORM=web clean + $(MAKE) -C files/lang clean diff --git a/files/web/dist/fheroes2.jpeg b/files/web/dist/fheroes2.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6368df48822bff55ce4ad7cebb5dca65aa054f03 GIT binary patch literal 79045 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

oS3yP1)LJgtSWmtb@$@?_(F(EF2a492+ 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 + + fheroes2 + + + + + + + + + +

+ +
+
+
+ + +
+
+ + diff --git a/files/web/readme b/files/web/readme new file mode 100644 index 00000000000..deeb60a7bc8 --- /dev/null +++ b/files/web/readme @@ -0,0 +1,14 @@ +building with pthread: +1. modify src/dist/Makefile.web to enable pthread support +2. modify src/engine/thread.cpp to allow spawn threads +3. use patch sdl2_mixer.py; PR and issue description https://github.com/emscripten-core/emscripten/pull/23094 +4. check how to enable SharedArrayBuffer, options: serve with custom headers, use service worker to intercept request, use custom browser flags + +docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ + sh -c \ + 'cp -f files/web/sdl2_mixer.py /emsdk/upstream/emscripten/tools/ports/sdl2_mixer.py && apt update && apt install -y gettext && emmake make -f Makefile.web' + +building without pthread: +docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ + sh -c \ + 'apt update && apt install -y gettext && emmake make -f Makefile.web' diff --git a/files/web/sdl2_mixer.py b/files/web/sdl2_mixer.py new file mode 100644 index 00000000000..a4723fd6152 --- /dev/null +++ b/files/web/sdl2_mixer.py @@ -0,0 +1,126 @@ +# Copyright 2016 The Emscripten Authors. All rights reserved. +# Emscripten is available under two separate licenses, the MIT license and the +# University of Illinois/NCSA Open Source License. Both these licenses can be +# found in the LICENSE file. + +import os + +TAG = 'release-2.8.0' +HASH = '494ccd74540f74e717f7e4f1dc7f96398c0f4b1883ab00c4a76b0c7239bd2c185cb4358a35ef47819c49e7c14dac7c37b98a29c7b5237478121571f5e7ac4dfc' + +deps = ['sdl2'] +variants = { + 'sdl2_mixer-mp3': {'SDL2_MIXER_FORMATS': ["mp3"]}, + 'sdl2_mixer-none': {'SDL2_MIXER_FORMATS': []}, + 'sdl2_mixer-mp3-mt': {'SDL2_MIXER_FORMATS': ["mp3"], 'PTHREADS': 1}, + 'sdl2_mixer-none-mt': {'SDL2_MIXER_FORMATS': [], 'PTHREADS': 1}, +} + + +def needed(settings): + return settings.USE_SDL_MIXER == 2 + + +def get_lib_name(settings): + settings.SDL2_MIXER_FORMATS.sort() + formats = '-'.join(settings.SDL2_MIXER_FORMATS) + + libname = 'libSDL2_mixer' + if formats != '': + libname += '-' + formats + if settings.PTHREADS: + libname += '-mt' + libname += '.a' + + return libname + + +def get(ports, settings, shared): + sdl_build = os.path.join(ports.get_build_dir(), 'sdl2') + assert os.path.exists(sdl_build), 'You must use SDL2 to use SDL2_mixer' + ports.fetch_project('sdl2_mixer', f'https://github.com/libsdl-org/SDL_mixer/archive/{TAG}.zip', sha512hash=HASH) + libname = get_lib_name(settings) + + def create(final): + source_path = ports.get_dir('sdl2_mixer', 'SDL_mixer-' + TAG) + flags = [ + '-sUSE_SDL=2', + '-O2', + '-DMUSIC_WAV', + ] + + if "ogg" in settings.SDL2_MIXER_FORMATS: + flags += [ + '-sUSE_VORBIS', + '-DMUSIC_OGG', + ] + + if "mp3" in settings.SDL2_MIXER_FORMATS: + flags += [ + '-sUSE_MPG123', + '-DMUSIC_MP3_MPG123', + ] + + if "mod" in settings.SDL2_MIXER_FORMATS: + flags += [ + '-sUSE_MODPLUG', + '-DMUSIC_MOD_MODPLUG', + ] + + if "mid" in settings.SDL2_MIXER_FORMATS: + flags += [ + '-DMUSIC_MID_TIMIDITY', + ] + + if settings.PTHREADS: + flags.append('-pthread') + + build_dir = ports.clear_project_build('sdl2_mixer') + include_path = os.path.join(source_path, 'include') + includes = [ + include_path, + os.path.join(source_path, 'src'), + os.path.join(source_path, 'src', 'codecs') + ] + ports.build_port( + source_path, + final, + build_dir, + flags=flags, + exclude_files=[ + 'playmus.c', + 'playwave.c', + 'main.c', + ], + exclude_dirs=[ + 'native_midi', + 'external', + 'Xcode', + ], + includes=includes, + ) + + ports.install_headers(include_path, target='SDL2') + + return [shared.cache.get_lib(libname, create, what='port')] + + +def clear(ports, settings, shared): + shared.cache.erase_lib(get_lib_name(settings)) + + +def process_dependencies(settings): + settings.USE_SDL = 2 + if "ogg" in settings.SDL2_MIXER_FORMATS: + deps.append('vorbis') + settings.USE_VORBIS = 1 + if "mp3" in settings.SDL2_MIXER_FORMATS: + deps.append('mpg123') + settings.USE_MPG123 = 1 + if "mod" in settings.SDL2_MIXER_FORMATS: + deps.append('libmodplug') + settings.USE_MODPLUG = 1 + + +def show(): + return 'sdl2_mixer (-sUSE_SDL_MIXER=2 or --use-port=sdl2_mixer; zlib license)' diff --git a/src/dist/Makefile b/src/dist/Makefile index 4e1c76db630..b8d4dce37fb 100644 --- a/src/dist/Makefile +++ b/src/dist/Makefile @@ -159,7 +159,11 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER $(MAKE) -C thirdparty/libsmacker CCFLAGS="$(CCFLAGS_TP)" CFLAGS="$(CFLAGS_TP)" CXXFLAGS="$(CXXFLAGS_TP)" CPPFLAGS="$(CPPFLAGS_TP)" endif $(MAKE) -C engine +ifeq ($(PLATFORM),web) + $(MAKE) -C web +else $(MAKE) -C fheroes2 +endif ifdef FHEROES2_WITH_TOOLS $(MAKE) -C tools endif @@ -169,5 +173,9 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER $(MAKE) -C thirdparty/libsmacker clean endif $(MAKE) -C engine clean +ifeq ($(PLATFORM),web) + $(MAKE) -C web clean +else $(MAKE) -C fheroes2 clean +endif $(MAKE) -C tools clean diff --git a/src/dist/Makefile.web b/src/dist/Makefile.web new file mode 100644 index 00000000000..c41babe7a8a --- /dev/null +++ b/src/dist/Makefile.web @@ -0,0 +1,40 @@ +########################################################################### +# fheroes2: https://github.com/ihhub/fheroes2 # +# Copyright (C) 2021 - 2024 # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +########################################################################### + +CCFLAGS := $(filter-out -pthread,$(CCFLAGS)) --use-port=sdl2_mixer \ + --use-port=sdl2 \ + --use-port=zlib + +LDFLAGS := $(filter-out -pthread,$(LDFLAGS)) -sENVIRONMENT=web \ + --preload-file ../../../files/data/resurrection.h2d@/files/data/resurrection.h2d \ + --preload-file ../../../files/lang/@/files/lang/ \ + --preload-file ../../../files/soundfonts/fheroes2.sf3@/files/soundfonts/fheroes2.sf3 \ + -sNO_DISABLE_EXCEPTION_CATCHING \ + -sSTACK_SIZE=262144 \ + -sINITIAL_MEMORY=128mb \ + -sENVIRONMENT=web \ + -sASYNCIFY \ + -sASYNCIFY_STACK_SIZE=20480 \ + -lidbfs.js + +ifdef FHEROES2_WITH_DEBUG +LDFLAGS := $(LDFLAGS) -gsource-map +CCFLAGS := $(CCFLAGS) -gsource-map +endif diff --git a/src/dist/web/Makefile b/src/dist/web/Makefile new file mode 100644 index 00000000000..f08c7ebdce2 --- /dev/null +++ b/src/dist/web/Makefile @@ -0,0 +1,55 @@ +########################################################################### +# fheroes2: https://github.com/ihhub/fheroes2 # +# Copyright (C) 2021 - 2024 # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +########################################################################### + +DEPLIBS := ../engine/libengine.a +CCFLAGS := $(CCFLAGS) -I../../engine + +ifndef FHEROES2_WITH_SYSTEM_SMACKER +DEPLIBS := $(DEPLIBS) ../thirdparty/libsmacker/libsmacker.a +CCFLAGS := $(CCFLAGS) -I../../thirdparty/libsmacker +endif + +SOURCEROOT := ../../fheroes2 +SOURCEDIRS := $(filter %/,$(wildcard $(SOURCEROOT)/*/)) +SOURCES := $(wildcard $(SOURCEROOT)/*/*.cpp) + +VPATH := $(SOURCEDIRS) + +.PHONY: all clean + +all: fheroes2.js + +fheroes2.js: $(notdir $(patsubst %.cpp, %.o, $(SOURCES))) $(DEPLIBS) + xgettext -d fheroes2.js --language=JavaScript -F -k_ -k_n:1,2 -o fheroes2.pot $(sort $(SOURCES)) + $(MAKE) -C ../../../files/lang + $(CXX) -o $@ $^ $(LIBS) $(LDFLAGS) + rm -f *.d *.o *.tmp *.pot~ *.pot + mkdir -p dist + mv -f fheroes2.* dist + cp ../../../files/web/dist/* dist + +%.o: %.cpp + $(CXX) -c -MD $< $(addprefix -I, $(SOURCEDIRS)) $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS) + +include $(wildcard *.d) + +clean: + rm -f *.d *.o fheroes2.js fheroes2.wasm fheroes2.wasm.* fheroes2.data fheroes2.pot fheroes2.pot~ + rm -rf dist diff --git a/src/engine/thread.cpp b/src/engine/thread.cpp index 10f86736900..9340ad91096 100644 --- a/src/engine/thread.cpp +++ b/src/engine/thread.cpp @@ -22,21 +22,23 @@ #include #include +#include "logging.h" namespace MultiThreading { void AsyncManager::createWorker() { +#if !defined( __EMSCRIPTEN__ ) // disable pthread for web target if ( !_worker ) { _runFlag = true; _worker = std::make_unique( AsyncManager::_workerThread, this ); - { std::unique_lock lock( _mutex ); _masterNotification.wait( lock, [this] { return !_runFlag; } ); } } +#endif } void AsyncManager::stopWorker() @@ -59,8 +61,15 @@ namespace MultiThreading void AsyncManager::notifyWorker() { _runFlag = true; - +#if !defined( __EMSCRIPTEN__ ) _workerNotification.notify_all(); +#else + if ( this->_exitFlag ) return; + const bool moreTasks = this->prepareTask(); + if ( !moreTasks ) this->_runFlag = false; + + this->executeTask(); +#endif } void AsyncManager::_workerThread( AsyncManager * manager ) diff --git a/src/fheroes2/game/game_hotkeys.cpp b/src/fheroes2/game/game_hotkeys.cpp index be067217449..f09afae05e8 100644 --- a/src/fheroes2/game/game_hotkeys.cpp +++ b/src/fheroes2/game/game_hotkeys.cpp @@ -51,6 +51,10 @@ #include "ui_dialog.h" #include "ui_language.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + namespace { struct HotKeyEventInfo @@ -463,6 +467,11 @@ void Game::HotKeySave() const std::string & data = getHotKeyFileContent(); file.write( data.data(), data.size() ); +#ifdef __EMSCRIPTEN__ + EM_ASM( + FS.syncfs( err => err && console.warn( "Error saving:", err ) ) + ); +#endif } void Game::globalKeyDownEvent( const fheroes2::Key key, const int32_t modifier ) diff --git a/src/fheroes2/game/game_io.cpp b/src/fheroes2/game/game_io.cpp index b4e9c0d7bb0..a9125a5f036 100644 --- a/src/fheroes2/game/game_io.cpp +++ b/src/fheroes2/game/game_io.cpp @@ -47,6 +47,10 @@ #include "world.h" #include "zzlib.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + namespace { const std::string autoSaveName{ "AUTOSAVE" }; @@ -154,7 +158,11 @@ bool Game::Save( const std::string & filePath, const bool autoSave /* = false */ if ( !autoSave ) { Game::SetLastSaveName( filePath ); } - +#ifdef __EMSCRIPTEN__ + EM_ASM( + FS.syncfs( err => err && console.warn( "Error saving:", err ) ) + ); +#endif return true; } diff --git a/src/fheroes2/system/settings.cpp b/src/fheroes2/system/settings.cpp index 20d5e9636ed..a13dce6c92b 100644 --- a/src/fheroes2/system/settings.cpp +++ b/src/fheroes2/system/settings.cpp @@ -47,6 +47,10 @@ #include "ui_language.h" #include "version.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + #define STRINGIFY( DEF ) #DEF #define EXPANDDEF( DEF ) STRINGIFY( DEF ) @@ -358,7 +362,11 @@ bool Settings::Save( const std::string_view fileName ) const const std::string & data = String(); file.write( data.data(), data.size() ); - +#ifdef __EMSCRIPTEN__ + EM_ASM( + FS.syncfs( err => err && console.warn( "Error saving:", err ) ) + ); +#endif return true; } From 7e491d708247d012d6f995ffcad22a213f3f6e2c Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 03:35:34 +0300 Subject: [PATCH 02/23] Deal with AsyncManager --- src/engine/thread.cpp | 63 +++++++++++++++++++++++++++++++++++++------ src/engine/thread.h | 5 ++-- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/engine/thread.cpp b/src/engine/thread.cpp index 9340ad91096..7f9c8c01083 100644 --- a/src/engine/thread.cpp +++ b/src/engine/thread.cpp @@ -22,16 +22,46 @@ #include #include + #include "logging.h" +namespace +{ +#ifdef __EMSCRIPTEN__ + class MutexUnlocker + { + public: + explicit MutexUnlocker( std::mutex & mutex ) + : _mutex( mutex ) + { + _mutex.unlock(); + } + + MutexUnlocker( const MutexUnlocker & ) = delete; + + ~MutexUnlocker() + { + _mutex.lock(); + } + + MutexUnlocker & operator=( const MutexUnlocker & ) = delete; + + private: + std::mutex & _mutex; + }; +#endif +} + namespace MultiThreading { void AsyncManager::createWorker() { -#if !defined( __EMSCRIPTEN__ ) // disable pthread for web target + // Emscripten has no pthread support. The worker thread should not be started. +#ifndef __EMSCRIPTEN__ if ( !_worker ) { _runFlag = true; _worker = std::make_unique( AsyncManager::_workerThread, this ); + { std::unique_lock lock( _mutex ); @@ -43,6 +73,10 @@ namespace MultiThreading void AsyncManager::stopWorker() { +#ifdef __EMSCRIPTEN__ + // Emscripten has no pthread support. The worker thread should not be running here. + assert( !_worker ); +#else if ( _worker ) { { const std::scoped_lock lock( _mutex ); @@ -56,19 +90,32 @@ namespace MultiThreading _worker->join(); _worker.reset(); } +#endif } void AsyncManager::notifyWorker() { _runFlag = true; -#if !defined( __EMSCRIPTEN__ ) - _workerNotification.notify_all(); -#else - if ( this->_exitFlag ) return; - const bool moreTasks = this->prepareTask(); - if ( !moreTasks ) this->_runFlag = false; - this->executeTask(); + // Emscripten has no pthread support, so instead of passing tasks to the worker thread, we will process them immediately in the current thread. +#ifdef __EMSCRIPTEN__ + assert( !_exitFlag ); + + while ( _runFlag ) { + const bool moreTasks = prepareTask(); + if ( !moreTasks ) { + _runFlag = false; + } + + { + // In accordance with the contract, the _mutex should NOT be acquired while calling the executeTask(). + MutexUnlocker unlocker( _mutex ); + + executeTask(); + } + } +#else + _workerNotification.notify_all(); #endif } diff --git a/src/engine/thread.h b/src/engine/thread.h index d3f9bb00ae2..bf6d79e4d05 100644 --- a/src/engine/thread.h +++ b/src/engine/thread.h @@ -53,11 +53,10 @@ namespace MultiThreading // Notify the worker thread about a new task. The _mutex should be acquired while calling this method. void notifyWorker(); - // Prepare a task which requires mutex lock. Returns true if more tasks are available. + // Prepare the next task. The _mutex will be acquired while calling this method. Returns true if more tasks are available. virtual bool prepareTask() = 0; - // Task execution is done in non-thread safe mode! No mutex lock for any means of synchronizations are - // done for this call. + // Execute the next task. NOTE WELL: the _mutex will NOT be acquired while calling this method. virtual void executeTask() = 0; private: From 0c31b7c4b9ea18565ef6adfcb9374e1536e3b42c Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 04:11:48 +0300 Subject: [PATCH 03/23] Move the FS.syncfs() call to the serialize.cpp --- src/engine/serialize.cpp | 13 +++++++++++++ src/engine/serialize.h | 2 +- src/fheroes2/game/game_hotkeys.cpp | 22 +++++++--------------- src/fheroes2/game/game_io.cpp | 10 +--------- src/fheroes2/system/settings.cpp | 22 ++++++---------------- 5 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/engine/serialize.cpp b/src/engine/serialize.cpp index d528e8b5f72..eee3d1e49ee 100644 --- a/src/engine/serialize.cpp +++ b/src/engine/serialize.cpp @@ -29,6 +29,10 @@ #include #include +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "logging.h" namespace @@ -395,6 +399,11 @@ std::string_view ROStreamBuf::getStringView( const size_t size /* = 0 */ ) return { reinterpret_cast( strBeg ), static_cast( strEnd - strBeg ) }; } +StreamFile::~StreamFile() +{ + close(); +} + bool StreamFile::open( const std::string & fn, const std::string & mode ) { _file.reset( std::fopen( fn.c_str(), mode.c_str() ) ); @@ -410,6 +419,10 @@ bool StreamFile::open( const std::string & fn, const std::string & mode ) void StreamFile::close() { _file.reset(); + +#ifdef __EMSCRIPTEN__ + EM_ASM( FS.syncfs( err = > err && console.warn( "FS.syncfs() error:", err ) ) ); +#endif } size_t StreamFile::size() diff --git a/src/engine/serialize.h b/src/engine/serialize.h index efc71abfb30..34552198c6a 100644 --- a/src/engine/serialize.h +++ b/src/engine/serialize.h @@ -597,7 +597,7 @@ class StreamFile final : public IStreamBase, public OStreamBase StreamFile( const StreamFile & ) = delete; - ~StreamFile() override = default; + ~StreamFile() override; StreamFile & operator=( const StreamFile & ) = delete; diff --git a/src/fheroes2/game/game_hotkeys.cpp b/src/fheroes2/game/game_hotkeys.cpp index f09afae05e8..3065b5c7d5e 100644 --- a/src/fheroes2/game/game_hotkeys.cpp +++ b/src/fheroes2/game/game_hotkeys.cpp @@ -43,6 +43,7 @@ #include "localevent.h" #include "logging.h" #include "players.h" +#include "serialize.h" #include "settings.h" #include "system.h" #include "tinyconfig.h" @@ -51,10 +52,6 @@ #include "ui_dialog.h" #include "ui_language.h" -#ifdef __EMSCRIPTEN__ -#include -#endif - namespace { struct HotKeyEventInfo @@ -456,22 +453,17 @@ void Game::HotKeysLoad( const std::string & filename ) void Game::HotKeySave() { - // Save the latest information into the file. const std::string filename = System::concatPath( System::GetConfigDirectory( "fheroes2" ), "fheroes2.key" ); - std::fstream file( filename.data(), std::fstream::out | std::fstream::trunc ); - if ( !file ) { - ERROR_LOG( "Unable to open hotkey settings file " << filename ) + StreamFile fileStream; + if ( !fileStream.open( filename, "w" ) ) { + ERROR_LOG( "Unable to open the hotkey settings file " << filename ) return; } - const std::string & data = getHotKeyFileContent(); - file.write( data.data(), data.size() ); -#ifdef __EMSCRIPTEN__ - EM_ASM( - FS.syncfs( err => err && console.warn( "Error saving:", err ) ) - ); -#endif + const std::string data = getHotKeyFileContent(); + + fileStream.putRaw( data.data(), data.size() ); } void Game::globalKeyDownEvent( const fheroes2::Key key, const int32_t modifier ) diff --git a/src/fheroes2/game/game_io.cpp b/src/fheroes2/game/game_io.cpp index a9125a5f036..b4e9c0d7bb0 100644 --- a/src/fheroes2/game/game_io.cpp +++ b/src/fheroes2/game/game_io.cpp @@ -47,10 +47,6 @@ #include "world.h" #include "zzlib.h" -#ifdef __EMSCRIPTEN__ -#include -#endif - namespace { const std::string autoSaveName{ "AUTOSAVE" }; @@ -158,11 +154,7 @@ bool Game::Save( const std::string & filePath, const bool autoSave /* = false */ if ( !autoSave ) { Game::SetLastSaveName( filePath ); } -#ifdef __EMSCRIPTEN__ - EM_ASM( - FS.syncfs( err => err && console.warn( "Error saving:", err ) ) - ); -#endif + return true; } diff --git a/src/fheroes2/system/settings.cpp b/src/fheroes2/system/settings.cpp index a13dce6c92b..b363c15a8f2 100644 --- a/src/fheroes2/system/settings.cpp +++ b/src/fheroes2/system/settings.cpp @@ -47,10 +47,6 @@ #include "ui_language.h" #include "version.h" -#ifdef __EMSCRIPTEN__ -#include -#endif - #define STRINGIFY( DEF ) #DEF #define EXPANDDEF( DEF ) STRINGIFY( DEF ) @@ -352,21 +348,15 @@ bool Settings::Save( const std::string_view fileName ) const return false; } - const std::string cfgFilename = System::concatPath( System::GetConfigDirectory( "fheroes2" ), fileName ); - - std::fstream file; - file.open( cfgFilename.data(), std::fstream::out | std::fstream::trunc ); - if ( !file ) { + StreamFile fileStream; + if ( !fileStream.open( System::concatPath( System::GetConfigDirectory( "fheroes2" ), fileName ), "w" ) ) { return false; } - const std::string & data = String(); - file.write( data.data(), data.size() ); -#ifdef __EMSCRIPTEN__ - EM_ASM( - FS.syncfs( err => err && console.warn( "Error saving:", err ) ) - ); -#endif + const std::string data = String(); + + fileStream.putRaw( data.data(), data.size() ); + return true; } From 188897ed82f2ee94c8f03cffc1efaee360ca6999 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 04:55:39 +0300 Subject: [PATCH 04/23] Update the copyright headers --- Makefile.web | 2 +- files/web/sdl2_mixer.py | 25 +++++++++++++++++++++---- src/dist/Makefile | 2 +- src/dist/Makefile.web | 2 +- src/dist/web/Makefile | 2 +- src/engine/serialize.cpp | 2 +- src/engine/serialize.h | 2 +- src/engine/thread.cpp | 2 +- src/engine/thread.h | 2 +- src/fheroes2/game/game_hotkeys.cpp | 2 +- src/fheroes2/system/settings.cpp | 2 +- 11 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Makefile.web b/Makefile.web index f935cbe2080..d1177518625 100644 --- a/Makefile.web +++ b/Makefile.web @@ -1,6 +1,6 @@ ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2021 - 2024 # +# Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # diff --git a/files/web/sdl2_mixer.py b/files/web/sdl2_mixer.py index a4723fd6152..10a1f76624d 100644 --- a/files/web/sdl2_mixer.py +++ b/files/web/sdl2_mixer.py @@ -1,7 +1,24 @@ -# Copyright 2016 The Emscripten Authors. All rights reserved. -# Emscripten is available under two separate licenses, the MIT license and the -# University of Illinois/NCSA Open Source License. Both these licenses can be -# found in the LICENSE file. +########################################################################### +# fheroes2: https://github.com/ihhub/fheroes2 # +# Copyright (C) 2025 # +# # +# Copyright 2016 The Emscripten Authors. All rights reserved. # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +########################################################################### import os diff --git a/src/dist/Makefile b/src/dist/Makefile index b8d4dce37fb..66ce4995515 100644 --- a/src/dist/Makefile +++ b/src/dist/Makefile @@ -1,6 +1,6 @@ ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2021 - 2024 # +# Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # diff --git a/src/dist/Makefile.web b/src/dist/Makefile.web index c41babe7a8a..47f47ef3291 100644 --- a/src/dist/Makefile.web +++ b/src/dist/Makefile.web @@ -1,6 +1,6 @@ ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2021 - 2024 # +# Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # diff --git a/src/dist/web/Makefile b/src/dist/web/Makefile index f08c7ebdce2..aaf27ad5b1f 100644 --- a/src/dist/web/Makefile +++ b/src/dist/web/Makefile @@ -1,6 +1,6 @@ ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2021 - 2024 # +# Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # diff --git a/src/engine/serialize.cpp b/src/engine/serialize.cpp index eee3d1e49ee..234cf34dd33 100644 --- a/src/engine/serialize.cpp +++ b/src/engine/serialize.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2024 * + * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * diff --git a/src/engine/serialize.h b/src/engine/serialize.h index 34552198c6a..9e777d1a222 100644 --- a/src/engine/serialize.h +++ b/src/engine/serialize.h @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2024 * + * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * diff --git a/src/engine/thread.cpp b/src/engine/thread.cpp index 7f9c8c01083..7f9117600cb 100644 --- a/src/engine/thread.cpp +++ b/src/engine/thread.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2022 - 2023 * + * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * diff --git a/src/engine/thread.h b/src/engine/thread.h index bf6d79e4d05..4885dea2252 100644 --- a/src/engine/thread.h +++ b/src/engine/thread.h @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2022 * + * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * diff --git a/src/fheroes2/game/game_hotkeys.cpp b/src/fheroes2/game/game_hotkeys.cpp index 3065b5c7d5e..7e3950a3841 100644 --- a/src/fheroes2/game/game_hotkeys.cpp +++ b/src/fheroes2/game/game_hotkeys.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2024 * + * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * diff --git a/src/fheroes2/system/settings.cpp b/src/fheroes2/system/settings.cpp index b363c15a8f2..692fa931449 100644 --- a/src/fheroes2/system/settings.cpp +++ b/src/fheroes2/system/settings.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2024 * + * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * From 347352658ff600d4a68a11c2cbbe50b7013452c6 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 05:02:49 +0300 Subject: [PATCH 05/23] Apply the IWYU suggestions --- src/engine/thread.cpp | 2 -- src/fheroes2/game/game_hotkeys.cpp | 1 - src/fheroes2/system/settings.cpp | 1 - 3 files changed, 4 deletions(-) diff --git a/src/engine/thread.cpp b/src/engine/thread.cpp index 7f9117600cb..e396ae026fa 100644 --- a/src/engine/thread.cpp +++ b/src/engine/thread.cpp @@ -23,8 +23,6 @@ #include #include -#include "logging.h" - namespace { #ifdef __EMSCRIPTEN__ diff --git a/src/fheroes2/game/game_hotkeys.cpp b/src/fheroes2/game/game_hotkeys.cpp index 7e3950a3841..4df9820230e 100644 --- a/src/fheroes2/game/game_hotkeys.cpp +++ b/src/fheroes2/game/game_hotkeys.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/src/fheroes2/system/settings.cpp b/src/fheroes2/system/settings.cpp index 692fa931449..2b822b6365a 100644 --- a/src/fheroes2/system/settings.cpp +++ b/src/fheroes2/system/settings.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include From 00bab794e3d9ce84c921695c66aa17d369f7f6b2 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 05:24:19 +0300 Subject: [PATCH 06/23] Ignore the clang-format for JS code --- src/engine/serialize.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engine/serialize.cpp b/src/engine/serialize.cpp index 234cf34dd33..61d37eaaaa8 100644 --- a/src/engine/serialize.cpp +++ b/src/engine/serialize.cpp @@ -421,7 +421,9 @@ void StreamFile::close() _file.reset(); #ifdef __EMSCRIPTEN__ - EM_ASM( FS.syncfs( err = > err && console.warn( "FS.syncfs() error:", err ) ) ); + // clang-format off + EM_ASM( FS.syncfs( err => err && console.warn( "FS.syncfs() error:", err ) ) ); + // clang-format on #endif } From 7ba36046a530e830f9398429cfdb92a9123a3f94 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 05:40:22 +0300 Subject: [PATCH 07/23] Style nits --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bddbe0d8d26..7bc31a45eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -97,7 +97,7 @@ android/app/src/main/assets/files/ # Mac magic folders .DS_Store -#web build artifacts +# Web build artifacts *.wasm *.wasm.map fheroes2.js From 214fe9ab6bff1603990d42b89856ad09e2a38093 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 06:11:47 +0300 Subject: [PATCH 08/23] Move the sync operation to deleter --- src/engine/serialize.cpp | 24 +++++++++++++----------- src/engine/serialize.h | 6 ++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/engine/serialize.cpp b/src/engine/serialize.cpp index 61d37eaaaa8..8679caef495 100644 --- a/src/engine/serialize.cpp +++ b/src/engine/serialize.cpp @@ -399,11 +399,6 @@ std::string_view ROStreamBuf::getStringView( const size_t size /* = 0 */ ) return { reinterpret_cast( strBeg ), static_cast( strEnd - strBeg ) }; } -StreamFile::~StreamFile() -{ - close(); -} - bool StreamFile::open( const std::string & fn, const std::string & mode ) { _file.reset( std::fopen( fn.c_str(), mode.c_str() ) ); @@ -419,12 +414,6 @@ bool StreamFile::open( const std::string & fn, const std::string & mode ) void StreamFile::close() { _file.reset(); - -#ifdef __EMSCRIPTEN__ - // clang-format off - EM_ASM( FS.syncfs( err => err && console.warn( "FS.syncfs() error:", err ) ) ); - // clang-format on -#endif } size_t StreamFile::size() @@ -637,3 +626,16 @@ std::string StreamFile::getString( const size_t size /* = 0 */ ) return { buf.begin(), std::find( buf.begin(), buf.end(), 0 ) }; } + +int StreamFile::closeFile( std::FILE * f ) +{ + const int res = std::fclose( f ); + +#ifdef __EMSCRIPTEN__ + // clang-format off + EM_ASM( FS.syncfs( err => err && console.warn( "FS.syncfs() error:", err ) ) ); + // clang-format on +#endif + + return res; +} diff --git a/src/engine/serialize.h b/src/engine/serialize.h index 9e777d1a222..05883448e55 100644 --- a/src/engine/serialize.h +++ b/src/engine/serialize.h @@ -597,7 +597,7 @@ class StreamFile final : public IStreamBase, public OStreamBase StreamFile( const StreamFile & ) = delete; - ~StreamFile() override; + ~StreamFile() override = default; StreamFile & operator=( const StreamFile & ) = delete; @@ -669,7 +669,9 @@ class StreamFile final : public IStreamBase, public OStreamBase } } - std::unique_ptr _file{ nullptr, []( std::FILE * f ) { return std::fclose( f ); } }; + static int closeFile( std::FILE * f ); + + std::unique_ptr _file{ nullptr, closeFile }; }; namespace fheroes2 From a5aff48b06ac7afe36ca5b4f396d46a076a509f0 Mon Sep 17 00:00:00 2001 From: Roman Turchin Date: Fri, 3 Jan 2025 10:28:02 -0500 Subject: [PATCH 09/23] remove pthread related patch; update web build description; add pipeline --- .github/workflows/make.yml | 16 +++++ files/web/readme | 7 +- files/web/sdl2_mixer.py | 143 ------------------------------------- 3 files changed, 19 insertions(+), 147 deletions(-) delete mode 100644 files/web/sdl2_mixer.py diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index b61291a4ae7..a98f51d806a 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -342,3 +342,19 @@ jobs: artifactErrorsFailBuild: true prerelease: true replacesArtifacts: true + make-web: + runs-on: ubuntu-latest + steps: + - name: Checkout ↓️ + uses: actions/checkout@v4 + + - name: Install and Build ⚙ + run: | + docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 sh -c 'apt update && apt install -y gettext && emmake make -f Makefile.web' + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@v4 + if: ${{ github.event_name == 'push' }} + with: + branch: gh-pages # The branch the action should deploy to. + folder: src/dist/web/dist # The folder the action should deploy. diff --git a/files/web/readme b/files/web/readme index deeb60a7bc8..9c56a21c267 100644 --- a/files/web/readme +++ b/files/web/readme @@ -1,10 +1,9 @@ -building with pthread: +building with pthread requires emscripten sdk patching(valid for v3.1.74): 1. modify src/dist/Makefile.web to enable pthread support 2. modify src/engine/thread.cpp to allow spawn threads -3. use patch sdl2_mixer.py; PR and issue description https://github.com/emscripten-core/emscripten/pull/23094 +3. use patch sdl2_mixer.py; PR, patch itself and issue description can be found here https://github.com/emscripten-core/emscripten/pull/23094 4. check how to enable SharedArrayBuffer, options: serve with custom headers, use service worker to intercept request, use custom browser flags - -docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ +5. docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ sh -c \ 'cp -f files/web/sdl2_mixer.py /emsdk/upstream/emscripten/tools/ports/sdl2_mixer.py && apt update && apt install -y gettext && emmake make -f Makefile.web' diff --git a/files/web/sdl2_mixer.py b/files/web/sdl2_mixer.py deleted file mode 100644 index 10a1f76624d..00000000000 --- a/files/web/sdl2_mixer.py +++ /dev/null @@ -1,143 +0,0 @@ -########################################################################### -# fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2025 # -# # -# Copyright 2016 The Emscripten Authors. All rights reserved. # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the # -# Free Software Foundation, Inc., # -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -########################################################################### - -import os - -TAG = 'release-2.8.0' -HASH = '494ccd74540f74e717f7e4f1dc7f96398c0f4b1883ab00c4a76b0c7239bd2c185cb4358a35ef47819c49e7c14dac7c37b98a29c7b5237478121571f5e7ac4dfc' - -deps = ['sdl2'] -variants = { - 'sdl2_mixer-mp3': {'SDL2_MIXER_FORMATS': ["mp3"]}, - 'sdl2_mixer-none': {'SDL2_MIXER_FORMATS': []}, - 'sdl2_mixer-mp3-mt': {'SDL2_MIXER_FORMATS': ["mp3"], 'PTHREADS': 1}, - 'sdl2_mixer-none-mt': {'SDL2_MIXER_FORMATS': [], 'PTHREADS': 1}, -} - - -def needed(settings): - return settings.USE_SDL_MIXER == 2 - - -def get_lib_name(settings): - settings.SDL2_MIXER_FORMATS.sort() - formats = '-'.join(settings.SDL2_MIXER_FORMATS) - - libname = 'libSDL2_mixer' - if formats != '': - libname += '-' + formats - if settings.PTHREADS: - libname += '-mt' - libname += '.a' - - return libname - - -def get(ports, settings, shared): - sdl_build = os.path.join(ports.get_build_dir(), 'sdl2') - assert os.path.exists(sdl_build), 'You must use SDL2 to use SDL2_mixer' - ports.fetch_project('sdl2_mixer', f'https://github.com/libsdl-org/SDL_mixer/archive/{TAG}.zip', sha512hash=HASH) - libname = get_lib_name(settings) - - def create(final): - source_path = ports.get_dir('sdl2_mixer', 'SDL_mixer-' + TAG) - flags = [ - '-sUSE_SDL=2', - '-O2', - '-DMUSIC_WAV', - ] - - if "ogg" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_VORBIS', - '-DMUSIC_OGG', - ] - - if "mp3" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_MPG123', - '-DMUSIC_MP3_MPG123', - ] - - if "mod" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_MODPLUG', - '-DMUSIC_MOD_MODPLUG', - ] - - if "mid" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-DMUSIC_MID_TIMIDITY', - ] - - if settings.PTHREADS: - flags.append('-pthread') - - build_dir = ports.clear_project_build('sdl2_mixer') - include_path = os.path.join(source_path, 'include') - includes = [ - include_path, - os.path.join(source_path, 'src'), - os.path.join(source_path, 'src', 'codecs') - ] - ports.build_port( - source_path, - final, - build_dir, - flags=flags, - exclude_files=[ - 'playmus.c', - 'playwave.c', - 'main.c', - ], - exclude_dirs=[ - 'native_midi', - 'external', - 'Xcode', - ], - includes=includes, - ) - - ports.install_headers(include_path, target='SDL2') - - return [shared.cache.get_lib(libname, create, what='port')] - - -def clear(ports, settings, shared): - shared.cache.erase_lib(get_lib_name(settings)) - - -def process_dependencies(settings): - settings.USE_SDL = 2 - if "ogg" in settings.SDL2_MIXER_FORMATS: - deps.append('vorbis') - settings.USE_VORBIS = 1 - if "mp3" in settings.SDL2_MIXER_FORMATS: - deps.append('mpg123') - settings.USE_MPG123 = 1 - if "mod" in settings.SDL2_MIXER_FORMATS: - deps.append('libmodplug') - settings.USE_MODPLUG = 1 - - -def show(): - return 'sdl2_mixer (-sUSE_SDL_MIXER=2 or --use-port=sdl2_mixer; zlib license)' From 82ef6731d91ac7de08ca3536d0cfbe0231e328fa Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 18:25:41 +0300 Subject: [PATCH 10/23] Rename "web" to "emscripten", simplify the build, add CI --- .github/workflows/make.yml | 35 +++++ Makefile.web => Makefile.emscripten | 18 ++- Makefile.vita | 4 +- files/{web/dist => emscripten}/fheroes2.jpeg | Bin files/{web/dist => emscripten}/index.html | 0 files/web/readme | 14 -- files/web/sdl2_mixer.py | 143 ------------------ src/dist/Makefile | 8 +- .../{Makefile.web => Makefile.emscripten} | 16 +- src/dist/{web => fheroes2-ems}/Makefile | 9 +- 10 files changed, 63 insertions(+), 184 deletions(-) rename Makefile.web => Makefile.emscripten (83%) rename files/{web/dist => emscripten}/fheroes2.jpeg (100%) rename files/{web/dist => emscripten}/index.html (100%) delete mode 100644 files/web/readme delete mode 100644 files/web/sdl2_mixer.py rename src/dist/{Makefile.web => Makefile.emscripten} (91%) rename src/dist/{web => fheroes2-ems}/Makefile (85%) diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index b61291a4ae7..f1aca87b08a 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -342,3 +342,38 @@ jobs: artifactErrorsFailBuild: true prerelease: true replacesArtifacts: true + make-emscripten: + name: Make (Emscripten) + runs-on: ubuntu-latest + timeout-minutes: 30 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + - name: Build + run: | + docker run --rm -v "$(pwd):/src" -e FHEROES2_STRICT_COMPILATION=ON emscripten/emsdk:3.1.74 \ + sh -c "apt-get -y update && apt-get -y install gettext && emmake make -f Makefile.emscripten -j \"$(nproc)\"" + - name: Create package + run: | + # Translations and H2D files are already included in fheroes2.data + 7z a -bb1 -tzip -- fheroes2_emscripten.zip LICENSE changelog.txt fheroes2.data fheroes2.js fheroes2.wasm ./docs/README.txt ./files/emscripten/* + - uses: actions/upload-artifact@v4 + if: ${{ github.event_name == 'pull_request' }} + with: + name: fheroes2_emscripten.zip + path: fheroes2_emscripten.zip + if-no-files-found: error + - uses: ncipollo/release-action@v1 + if: ${{ github.event_name == 'push' }} + with: + artifacts: fheroes2_emscripten.zip + body: ${{ github.event.head_commit.message }} + token: ${{ secrets.GITHUB_TOKEN }} + name: Emscripten build (latest commit) + tag: fheroes2-emscripten-sdl2_dev + allowUpdates: true + artifactErrorsFailBuild: true + prerelease: true + replacesArtifacts: true diff --git a/Makefile.web b/Makefile.emscripten similarity index 83% rename from Makefile.web rename to Makefile.emscripten index d1177518625..07feece5450 100644 --- a/Makefile.web +++ b/Makefile.emscripten @@ -24,14 +24,20 @@ # FHEROES2_WITH_DEBUG: build in debug mode # FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) -PROJECT_NAME := fheroes2 -PROJECT_VERSION := $(file < version.txt) +.PHONY: all clean translations -.PHONY: all clean +all: fheroes2.js -all: - $(MAKE) -C src/dist PLATFORM=web +fheroes2.js: translations + $(MAKE) -C src/dist PLATFORM=emscripten + cp src/dist/fheroes2-ems/fheroes2.data . + cp src/dist/fheroes2-ems/fheroes2.js . + cp src/dist/fheroes2-ems/fheroes2.wasm . + +translations: + $(MAKE) -C files/lang clean: - $(MAKE) -C src/dist PLATFORM=web clean + $(MAKE) -C src/dist clean $(MAKE) -C files/lang clean + rm -f fheroes2.data fheroes2.js fheroes2.wasm diff --git a/Makefile.vita b/Makefile.vita index 18a547c6b23..956ec8d6694 100644 --- a/Makefile.vita +++ b/Makefile.vita @@ -1,6 +1,6 @@ ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2021 - 2024 # +# Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -40,7 +40,7 @@ fheroes2.vpk: eboot.bin param.sfo translations --add files/images/platform/psv/sce_sys/livearea/contents/template.xml=sce_sys/livearea/contents/template.xml \ --add files/data=files/data \ --add files/lang/vita_temp=files/lang \ - fheroes2.vpk + fheroes2.vpk rm -r files/lang/vita_temp translations: fheroes2.elf diff --git a/files/web/dist/fheroes2.jpeg b/files/emscripten/fheroes2.jpeg similarity index 100% rename from files/web/dist/fheroes2.jpeg rename to files/emscripten/fheroes2.jpeg diff --git a/files/web/dist/index.html b/files/emscripten/index.html similarity index 100% rename from files/web/dist/index.html rename to files/emscripten/index.html diff --git a/files/web/readme b/files/web/readme deleted file mode 100644 index deeb60a7bc8..00000000000 --- a/files/web/readme +++ /dev/null @@ -1,14 +0,0 @@ -building with pthread: -1. modify src/dist/Makefile.web to enable pthread support -2. modify src/engine/thread.cpp to allow spawn threads -3. use patch sdl2_mixer.py; PR and issue description https://github.com/emscripten-core/emscripten/pull/23094 -4. check how to enable SharedArrayBuffer, options: serve with custom headers, use service worker to intercept request, use custom browser flags - -docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ - sh -c \ - 'cp -f files/web/sdl2_mixer.py /emsdk/upstream/emscripten/tools/ports/sdl2_mixer.py && apt update && apt install -y gettext && emmake make -f Makefile.web' - -building without pthread: -docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \ - sh -c \ - 'apt update && apt install -y gettext && emmake make -f Makefile.web' diff --git a/files/web/sdl2_mixer.py b/files/web/sdl2_mixer.py deleted file mode 100644 index 10a1f76624d..00000000000 --- a/files/web/sdl2_mixer.py +++ /dev/null @@ -1,143 +0,0 @@ -########################################################################### -# fheroes2: https://github.com/ihhub/fheroes2 # -# Copyright (C) 2025 # -# # -# Copyright 2016 The Emscripten Authors. All rights reserved. # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the # -# Free Software Foundation, Inc., # -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -########################################################################### - -import os - -TAG = 'release-2.8.0' -HASH = '494ccd74540f74e717f7e4f1dc7f96398c0f4b1883ab00c4a76b0c7239bd2c185cb4358a35ef47819c49e7c14dac7c37b98a29c7b5237478121571f5e7ac4dfc' - -deps = ['sdl2'] -variants = { - 'sdl2_mixer-mp3': {'SDL2_MIXER_FORMATS': ["mp3"]}, - 'sdl2_mixer-none': {'SDL2_MIXER_FORMATS': []}, - 'sdl2_mixer-mp3-mt': {'SDL2_MIXER_FORMATS': ["mp3"], 'PTHREADS': 1}, - 'sdl2_mixer-none-mt': {'SDL2_MIXER_FORMATS': [], 'PTHREADS': 1}, -} - - -def needed(settings): - return settings.USE_SDL_MIXER == 2 - - -def get_lib_name(settings): - settings.SDL2_MIXER_FORMATS.sort() - formats = '-'.join(settings.SDL2_MIXER_FORMATS) - - libname = 'libSDL2_mixer' - if formats != '': - libname += '-' + formats - if settings.PTHREADS: - libname += '-mt' - libname += '.a' - - return libname - - -def get(ports, settings, shared): - sdl_build = os.path.join(ports.get_build_dir(), 'sdl2') - assert os.path.exists(sdl_build), 'You must use SDL2 to use SDL2_mixer' - ports.fetch_project('sdl2_mixer', f'https://github.com/libsdl-org/SDL_mixer/archive/{TAG}.zip', sha512hash=HASH) - libname = get_lib_name(settings) - - def create(final): - source_path = ports.get_dir('sdl2_mixer', 'SDL_mixer-' + TAG) - flags = [ - '-sUSE_SDL=2', - '-O2', - '-DMUSIC_WAV', - ] - - if "ogg" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_VORBIS', - '-DMUSIC_OGG', - ] - - if "mp3" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_MPG123', - '-DMUSIC_MP3_MPG123', - ] - - if "mod" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-sUSE_MODPLUG', - '-DMUSIC_MOD_MODPLUG', - ] - - if "mid" in settings.SDL2_MIXER_FORMATS: - flags += [ - '-DMUSIC_MID_TIMIDITY', - ] - - if settings.PTHREADS: - flags.append('-pthread') - - build_dir = ports.clear_project_build('sdl2_mixer') - include_path = os.path.join(source_path, 'include') - includes = [ - include_path, - os.path.join(source_path, 'src'), - os.path.join(source_path, 'src', 'codecs') - ] - ports.build_port( - source_path, - final, - build_dir, - flags=flags, - exclude_files=[ - 'playmus.c', - 'playwave.c', - 'main.c', - ], - exclude_dirs=[ - 'native_midi', - 'external', - 'Xcode', - ], - includes=includes, - ) - - ports.install_headers(include_path, target='SDL2') - - return [shared.cache.get_lib(libname, create, what='port')] - - -def clear(ports, settings, shared): - shared.cache.erase_lib(get_lib_name(settings)) - - -def process_dependencies(settings): - settings.USE_SDL = 2 - if "ogg" in settings.SDL2_MIXER_FORMATS: - deps.append('vorbis') - settings.USE_VORBIS = 1 - if "mp3" in settings.SDL2_MIXER_FORMATS: - deps.append('mpg123') - settings.USE_MPG123 = 1 - if "mod" in settings.SDL2_MIXER_FORMATS: - deps.append('libmodplug') - settings.USE_MODPLUG = 1 - - -def show(): - return 'sdl2_mixer (-sUSE_SDL_MIXER=2 or --use-port=sdl2_mixer; zlib license)' diff --git a/src/dist/Makefile b/src/dist/Makefile index 66ce4995515..103f1a860cc 100644 --- a/src/dist/Makefile +++ b/src/dist/Makefile @@ -159,8 +159,8 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER $(MAKE) -C thirdparty/libsmacker CCFLAGS="$(CCFLAGS_TP)" CFLAGS="$(CFLAGS_TP)" CXXFLAGS="$(CXXFLAGS_TP)" CPPFLAGS="$(CPPFLAGS_TP)" endif $(MAKE) -C engine -ifeq ($(PLATFORM),web) - $(MAKE) -C web +ifeq ($(PLATFORM),emscripten) + $(MAKE) -C fheroes2-ems else $(MAKE) -C fheroes2 endif @@ -173,8 +173,8 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER $(MAKE) -C thirdparty/libsmacker clean endif $(MAKE) -C engine clean -ifeq ($(PLATFORM),web) - $(MAKE) -C web clean +ifeq ($(PLATFORM),emscripten) + $(MAKE) -C fheroes2-ems clean else $(MAKE) -C fheroes2 clean endif diff --git a/src/dist/Makefile.web b/src/dist/Makefile.emscripten similarity index 91% rename from src/dist/Makefile.web rename to src/dist/Makefile.emscripten index 47f47ef3291..94c52ac6155 100644 --- a/src/dist/Makefile.web +++ b/src/dist/Makefile.emscripten @@ -18,20 +18,22 @@ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### -CCFLAGS := $(filter-out -pthread,$(CCFLAGS)) --use-port=sdl2_mixer \ +CCFLAGS := $(filter-out -pthread,$(CCFLAGS)) \ --use-port=sdl2 \ - --use-port=zlib + --use-port=sdl2_mixer \ + --use-port=zlib \ + -Wno-variadic-macro-arguments-omitted -LDFLAGS := $(filter-out -pthread,$(LDFLAGS)) -sENVIRONMENT=web \ +LDFLAGS := $(filter-out -pthread,$(LDFLAGS)) \ --preload-file ../../../files/data/resurrection.h2d@/files/data/resurrection.h2d \ --preload-file ../../../files/lang/@/files/lang/ \ --preload-file ../../../files/soundfonts/fheroes2.sf3@/files/soundfonts/fheroes2.sf3 \ - -sNO_DISABLE_EXCEPTION_CATCHING \ - -sSTACK_SIZE=262144 \ - -sINITIAL_MEMORY=128mb \ - -sENVIRONMENT=web \ -sASYNCIFY \ -sASYNCIFY_STACK_SIZE=20480 \ + -sENVIRONMENT=web \ + -sINITIAL_MEMORY=128mb \ + -sNO_DISABLE_EXCEPTION_CATCHING \ + -sSTACK_SIZE=262144 \ -lidbfs.js ifdef FHEROES2_WITH_DEBUG diff --git a/src/dist/web/Makefile b/src/dist/fheroes2-ems/Makefile similarity index 85% rename from src/dist/web/Makefile rename to src/dist/fheroes2-ems/Makefile index aaf27ad5b1f..200a2fe3c13 100644 --- a/src/dist/web/Makefile +++ b/src/dist/fheroes2-ems/Makefile @@ -37,13 +37,7 @@ VPATH := $(SOURCEDIRS) all: fheroes2.js fheroes2.js: $(notdir $(patsubst %.cpp, %.o, $(SOURCES))) $(DEPLIBS) - xgettext -d fheroes2.js --language=JavaScript -F -k_ -k_n:1,2 -o fheroes2.pot $(sort $(SOURCES)) - $(MAKE) -C ../../../files/lang $(CXX) -o $@ $^ $(LIBS) $(LDFLAGS) - rm -f *.d *.o *.tmp *.pot~ *.pot - mkdir -p dist - mv -f fheroes2.* dist - cp ../../../files/web/dist/* dist %.o: %.cpp $(CXX) -c -MD $< $(addprefix -I, $(SOURCEDIRS)) $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS) @@ -51,5 +45,4 @@ fheroes2.js: $(notdir $(patsubst %.cpp, %.o, $(SOURCES))) $(DEPLIBS) include $(wildcard *.d) clean: - rm -f *.d *.o fheroes2.js fheroes2.wasm fheroes2.wasm.* fheroes2.data fheroes2.pot fheroes2.pot~ - rm -rf dist + rm -f *.d *.o fheroes2.data fheroes2.js fheroes2.wasm From a4f870f6270b2c5946b90117a71db0f3f228a7c4 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 19:38:53 +0300 Subject: [PATCH 11/23] Don't run Docker manually --- .github/workflows/make.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index f1aca87b08a..f399ae28829 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -345,16 +345,22 @@ jobs: make-emscripten: name: Make (Emscripten) runs-on: ubuntu-latest + container: emscripten/emsdk:3.1.74 timeout-minutes: 30 defaults: run: shell: bash steps: - uses: actions/checkout@v4 + - name: Install dependencies + run: | + sudo apt-get -y update + sudo apt-get -y install gettext p7zip-full - name: Build run: | - docker run --rm -v "$(pwd):/src" -e FHEROES2_STRICT_COMPILATION=ON emscripten/emsdk:3.1.74 \ - sh -c "apt-get -y update && apt-get -y install gettext && emmake make -f Makefile.emscripten -j \"$(nproc)\"" + emmake make -f Makefile.emscripten -j "$(nproc)" + env: + FHEROES2_STRICT_COMPILATION: ON - name: Create package run: | # Translations and H2D files are already included in fheroes2.data From 1b03f36a19e45276b63b64687cf7c61f3df991a9 Mon Sep 17 00:00:00 2001 From: Roman Turchin Date: Fri, 3 Jan 2025 11:47:37 -0500 Subject: [PATCH 12/23] fix whitelisted folders resolve --- files/emscripten/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/files/emscripten/index.html b/files/emscripten/index.html index 0e0d03d0a05..99352febb69 100644 --- a/files/emscripten/index.html +++ b/files/emscripten/index.html @@ -122,7 +122,9 @@ files.filter(file => { const [fileName, ...path] = file.webkitRelativePath.split('/').reverse(); if (fileName.startsWith('.')) return false; - return path.some(folder => whitListed.includes(folder)) + return path + .map(folder => folder.toLocaleLowerCase()) + .some(folder => whitListed.includes(folder)) }).reduce((uploaded, file, _ignore, queue) => { const [fileName, ...path] = file.webkitRelativePath.split('/').reverse(); const [ignore, ...relativePath] = path.reverse(); From ed1f299bd75830be16ada7cfef446ad0e63df8ca Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 22:30:38 +0300 Subject: [PATCH 13/23] Forcibly reset the track position if music playback is started from the beginning --- src/engine/audio.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/audio.cpp b/src/engine/audio.cpp index f152d36e63d..7db0f758dfe 100644 --- a/src/engine/audio.cpp +++ b/src/engine/audio.cpp @@ -540,6 +540,8 @@ namespace // Either there is no need to resume music playback, or the resumption failed. Let's try to // start the playback from the beginning. if ( returnCode != 0 ) { + track->setPosition( 0 ); + returnCode = Mix_FadeInMusic( mus.get(), loopCount, musicFadeInMs ); if ( returnCode != 0 ) { From 3382fe4e9aa9f689b1fc5a399d6b933c3bbb0752 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 22:37:12 +0300 Subject: [PATCH 14/23] Update the copyright date --- src/engine/audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/audio.cpp b/src/engine/audio.cpp index 7db0f758dfe..731954a1ca4 100644 --- a/src/engine/audio.cpp +++ b/src/engine/audio.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2024 * + * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Andrey Afletdinov * From 885de6efba7f35e2fafc0b91348655fa6f7286d0 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 3 Jan 2025 22:45:55 +0300 Subject: [PATCH 15/23] Add comment --- src/engine/serialize.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/serialize.cpp b/src/engine/serialize.cpp index 8679caef495..e01fa529dcb 100644 --- a/src/engine/serialize.cpp +++ b/src/engine/serialize.cpp @@ -632,6 +632,7 @@ int StreamFile::closeFile( std::FILE * f ) const int res = std::fclose( f ); #ifdef __EMSCRIPTEN__ + // The following code is not C++ code, but JavaScript code. // clang-format off EM_ASM( FS.syncfs( err => err && console.warn( "FS.syncfs() error:", err ) ) ); // clang-format on From 37d06f16e17c6dd4f981a904c06fff7205ea4614 Mon Sep 17 00:00:00 2001 From: Roman Turchin Date: Fri, 3 Jan 2025 15:24:10 -0500 Subject: [PATCH 16/23] use heroes2-pixed font for wasm launcher --- files/emscripten/heroes2-pixed.otf | Bin 0 -> 143428 bytes files/emscripten/heroes2-pixed.ttf | Bin 0 -> 228612 bytes files/emscripten/index.html | 80 +++++++++++++++++++---------- files/emscripten/license.txt | 4 ++ 4 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 files/emscripten/heroes2-pixed.otf create mode 100644 files/emscripten/heroes2-pixed.ttf create mode 100644 files/emscripten/license.txt diff --git a/files/emscripten/heroes2-pixed.otf b/files/emscripten/heroes2-pixed.otf new file mode 100644 index 0000000000000000000000000000000000000000..d8667c2a93e77e763a6ace4e997ca0699b422a6c GIT binary patch literal 143428 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 literal 0 HcmV?d00001 diff --git a/files/emscripten/heroes2-pixed.ttf b/files/emscripten/heroes2-pixed.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d186d8773a338542c2845bc1450ee06276b11645 GIT binary patch literal 228612 zcmeFa54^5bRp7s#{T>8F1(FgK;UXBC7^bEu82ctBO*m3oIYotuMTJR4zo=niJ6Taf z4V4vBR#a4E{EA9HQJQQgDk^KJtZ1UT5j8ZSkvc`mz32B`Ywxw6{k-Qr_q^{p=K}qP z_kPw{Yp?%n?LW`+{=G7Y$WfAHCeJwFZt3-zy3=e`whn?kxzV|%+9&^k~h5W;!k<@S!(-k;DwjK zIPp_YcnS1JfKxAd%a_UX$?qyFp+f%FtvON@_@U>0VxmJYysN?gzUH4Yl>G5dPeoP9lYKiQa}iJS=G z`-f}gFj)(@6zKzL;D}Fq^=m#$qU>4!P{`VgwKSwX!?6Cl z)ZQ?( z#+)%$p3zch8z*>-H8;zv%GSVYqxz<&G(6W)T4ierN~fY{F&Qf!lwYyhsh<#w4;#x! zn|@x;%2(R*g$~dYTN!gzndPTCx#$i_M4%OGUz859%Ahq*0aWHXCH6+1`qUa6EH`-g zjLNe(AnP62=OM(Bzt%7hYbukCpgwvqorIq1&w<7j8Yn zO-FU-K^FV4xEUE>anb@Di>>A#fDKp*PwQ&_Ql$@qbzZghO|ewD;#_+jx5k!VDz*db z)AFig^Mj8G&ULIh&^o7^_Cl&GmYTx?yq4u-imrM>`P>zrUw9=(cHmMey@JYRzvtNBTtuJggZ)-_kHLt{1jSo{TW%MaS> zs@QsxH};^_nZ~#RJqV91a+pHIZvsor6RiBTRO0%)YF1L=Bcr5?vSgW z`TRrdd?GjfiZ{eUHvo;F80XP%$&>X4&vjI8F{Rl0*yPAsJi#s%f2JR?^D%m=Z)3%b ztv||_5`V2?_z$o7-s~1M^j2QtY%}A!3ujxdLOOdyL%jbsl5QZPUJHe5lS2@qGVR9s9a+ zyxBbO8lRplHE;8J^h#^txmauXDVbFqp4?|*(DugH|(_98f1*O}XgtqyEzXrW5 zXnc*m3P{A@|8lV2Cy`@l#SvMbbwUF?bV_t8j^i)Wbi{jP?TEKC{&ISDn0$hKquexH zGkoXpJ;M(UHx4%s?;PGcd|>!L;i=)I@S+gIt7hLa`}Wy)&%Sr|{j>izd)w^ovv&j5_9tuqdg2e9_`@gu%ZclIj@xtMo;`b>zUSljykyT!CqMnP^)nuP z<@!g%`iIte5Oa_GsQfIkzH9it;fIE|55G9%;n#-yhX=xm;pFg=@G@duJ^QY?ShDt* z8tV>X39+s}@j+r8Ut_)4V%>kn{jba)9oFyHSnGeae(U;s)_-;VUF*NRe#`nVt-o{q zXV%}oe&hO2uHUf!FER@E?6V+JQ$q@Ms4f?ZBfQc(en%*?~vzR35!k+0FIzsINym@Ms4f?ZBfQc(enD zq63%URN;EyPF{N1!%Huh^6FO>c?_(_oC@%{gu~$F*bL4)BS@KH~)danJaO$a9JD-0OimMLy}RBG1F`^9lC+`$S&w zHjz(0laFf<nNC-S}FO zy=RJi>gmA!A}@pYvTH@o#rE6;p#So#MLrGrD}eK^0B#of^c#VFBA{`zgFaHFBSQJ?h^Sr;0oXyju-ilCx~2mF7OeNZ#)9HPvojQ zMAGddZ@yRLKSO`hK9RS;|7LuB%R5BA^;(gu@%?QV0_c4^{=Xgmf7v5)O%(YK;5+gA zoezjy`#6#BI#uMm1t9`qws$0N|7Ijz5)Cbz)zko@>8!7xe@%+*uVWkk)OFt6 zy;$V;?h(0z*mvOL_wNw-gL6gx@O*$=-haEuADt)i$HxO#i2TW=z&?>by+GuDV)JLj zyz6R_zkvP=^#AgDk$v}z{1yK1hW_hIMDBT;$lqKe^0)67`CsI7?*k(L`xueG$KQR= z6#2kSA|HhQhmVNde~ZXJ;{QXpm5(}o1l@l+TjZa~>46(X{so`^3jXNjA`b%lpDS|U z1mJyqa_A$xPI;#c!)-EzOJ(3y_F?S;84kNrhQ}~I{H-z^afJ*=LO=Ed8IEH7xOdC& z_y=S-`g9qNd94h`-YCPzz<=T$G8_l}agUSXNeb|e2cCSt3{PDHz$e@#!_%&j;Y56L zz6^WLmEq(|Wq3NgQ!bR@)YE0)j2S+jHx53YoKCw>hG)J;hG)G%hEG7}*_Q(QWH|jn z89wn6;2s&y!0#s=1Kcaa^G}uG1t-Yx$iOMy?hT849OmLc9I!(QTj>M_810J)!grwpHViwx&oEW@YYBg1DL4-o&A56JK; z_!nUFSr^LiYI1zd`M~>R_#9$?E_$y$9e7ZN&pQsdSB4A07c&0Bvt{_AGiA64pRdE_ zb?{z)oeUQf?@LaQ;Y-(KxFpH&WjDz1<@oywV!ZKjGJGXI-$bsL-6+FX-6g|U-!8-D zdvDWerXMOpA5e&z+E!@3i03d zpbYPRiwwVt{(F$W=L+5|yi$huqW9l#lY#v`+(w*VhyD%V_7i0It>?<{+u+|p_kHO8 z?ptK|y%)&vKQ5Euj!R_t{aa-Cg9~N&LwvrUod1X%|CqY}1i14$8UFMmGW;3(cO56g zpOed@AzK-z~#Q%D9zu`JziY5G~<0X9KB@(Uz(k&9+415!Q-*SzFZy}#= z1z&x=gm1e^!hbna!ZpBmTrS}|&zJCDuaKfjIb@1Xm>;{am)F8trSM8f}gu7o?Fe;>O) zxL(2^-Xh_Tj+gMq@c-mG33t9*!v8#1!k@iG!d-Vr`1AKm_{$R{?As&Zudu)SQVD;Z zCEP>ae|xrs{{`>fw@LUra{k}c@%QN6cRFytgb(8PgLg@|e+{@@!aw5gL&W?rvX8+3 zKj432{Ljc9xL3lzJSgF#M@V?^Yzg}>mT=%564oD-nPiy_Z;@HJPG+;4fO}-Nb}Dc& za09^ju-5{7uK6($xCXdcW`_%KIdHGcj(ES!j(m;G9(z1+m&}fOKxU8UecUI!TV_X} z09+}vV~`z#?AYsN_A&cp_C)lbc)QGwBgV%jnSI=)GJ6t!o_vYSp7Nl~PQdSp;62En ze!k331)c%#w71CYS$kym?6pV1dO#0Pr+?3Vx6EE}kIc?GTR(r!JLWvX(?aG{K1`0_ zbL||m!~EmU^%t(cX#E57Tk9{<3mNo%^4kaAxc)A+#liE2ryTfOdE)TY;VJunCwy|D zxo7)o{L22QApnsS$Us;U9-wgXm{i)0@{qaLi)zP5&=Yr*d}w@r+1!MFNfhqgFMC$V@gvp3HxU-gu4c`2Isxc?FQU;)XeDH5E3Mcxq1Utb z_dqf^vdyrs$_;+|QQ9=$`j+Kvd?Pg)$aijHpH6atDHvyA|5O5 zGgl4E0o=S<9=5(-w0Ry|UR8)_9*L^6VEw4rBN^XivFglY-N#ypJUfE8#RvheXgUXeJbZF(hQ`6>$&M1xE4oo6ib8{8SVKy z1(l|jwT~)C3m7CMcFKGXm}$0pPvQ1@GGf4A2d_)9HA8jN{JubzO1`S2`!Zx%a*cW< z!|Ek31SA?`9$Jr(^|Sy&M{j^%AUJ%2fu6 zaW7NaYwWH>=9HPzd$X3UR;yLDswG5574|DGb{V_VM!T(w#jbgAZZ(mGNs zZFQv)OZS3WyLjq5FWO-XZn5CgRC;OtF{&eTI00HsmR+nt6WFx8aLXN zwqyovnPh}YgKS)J*N-P3EF)V98KXFYWthrXuYDdzvFVk+NNna6=c46aEF1VfS6I%_ z@*W*7Pd!*p^e=^N-;&vxea0+Ri1>tD zl%ev5RI(fIZ(Y+?Jl1`N+`D<_gY`9YicX)`V&OZ&a;PIZldw%%6A{$z@XfArrkQKb zYLzWkv1jD>WgA?rM{iNLDn=ZgU({!s`p@Cf_ksl@+GdW)KEGF zwku6y9Ch}=sbr{pc;&B2yQp~+zD*w=i{H9OIN!v_gs(bX+&Qb>!@Op1)p{g$4$tId zYTfc-YcdfZ=p*$j+@q-6?~+V_KXGO-M*JKIpNI~bwUO-)-(WDHurEaN(+fimM;>oev znuTINvvW)tbwv!OK>$mFRb(N|{0>JCK zsKDcR^BxD)&m&CioS#Oy>2~9?EA2dZ_KLlWb6$xyU!(3<+aL*Dh1_9i)%Rn;t0-KP zpy6D_eQhmLs{Ae2)Eys)^a`!REN8)Ql zEf1(Yyf*u(cnt8|v*L*kW3wG~tgW^$p0&!ndT!>udRwL@n_cwnj-_I^gR7iWu&;v< zx30&s!OZFgdv=V+`kt|DeQs^p)aX6!UDXVgA3%!dYcoBQw3_l*OHhk$Y}fvdXC7s& z$!nR#kmZw>tz~iv>AZVni&C>tT6baFX{kncoTXG#vHDP5_obLeETC(3B2j(<6aywp zg>K`_x`t<-A~NVEgRFF!(@Y;$+@0=Aaii0ir|}q@JkMeHo|mspzm=()Xt)Q}3~}^q zmhe2PULmZEsc`5s)jGt{ zi+k$l$34_aEbpLeb^GT^johMT8T+?@UQ|n0&zyxy+;hOOkDa%uw(j|1sZZD7i|@lg@OWU%Hcd*7cSK;8LnQ?wk)buh*N8efXsCAC~J|cet%l2OrIZEWU$RWJmuH@VsmfLYaa3*_Gdz0 zMWZvBr;_c$-XU{-(enCy$Avg*sHS;N1-s=u_L)__^{DE%tYWd(asPU!-G3h~&slXP zhU(AqNMpVp&ui)PRGE*J)=Bid=VU6)h{0|#KDC7d-#p||u6o8#6~|H5y%SMyuIlr) zmFu2lMWlt#%aorB^c8r)1#bbcy-sfv>{HkkXshI@Dwr7s! z*B6(#@^8GtSZsW^95X&+^$*tB^t-K=3p!edkF6$ny2FjGvfd|rxC(03_q@y`tEgS3+$Rk>o@~omwUy= zONH+|U*o-QN!`}YDa+Nb5#57lVG(LH&&GAEc5F0r(~H%<)#kYdlzMCT;5GZ$yySX? z0CzQZ#)??cFt6$AD##3hiT^?~xNAJx9;Eufgw@)mnAk%l=%w!#BHf ze;{Gy=X348qk8mgJW|UFx$-sue7EUw)l6VCygR<9&5O!nwN|X-3@DDBSH`v;6$51s z*Rm<{=&)s3~7WK38ynog+jT%Sr9vH4N=b2s}br;#U4xs0DJ?>*U-JfQ?uG3>g z<+#-kP^g*Wrzc6A;j^SF&`kuC!DDYOft3l;>gozeHKawz$@Ae z`<-52jnQq*%t!LEd$e(q5*_UP&9K`mHl1oy`n2J5NI14NfR?RdVIA2_wmU||TYv6L zuh)w*@}1FVRWtL5bJ$i9ym`EN{u)EI?Lf0CY<#(=Vh=KS7{cfaj0)9LJ>^ zLO*9u#0B3QXj+}M<`x)N-%y+RRt@zZO0I`9m_I{Pu|^{n$}?6YjYHjsE%%C$^(vB= zLN1_QmG4(r8^iNxicL2){VJXRM6}IFmS(9|dM#=mI=bebLYBv``U>>?Iijn;vt1NV z^KyBAl6eQZ$|IV&X!kX*XGX{ZBIUbB(_yGGqcgapE8p7AH$1lfd_@}lsI7wC6N5cV zi?6Z_q@oWME98;(jA|Awvo==U07!_;!%^~#arOBs+yqCA0Nbs(=Ah$Bw;bX1{q(-| zw$O80rGxlTekW5}J-1a1y&v#shJ)}3Wlx;6L_KPch1pi@{xn{HlKa)b;-{8NrC1{+ zTdcfh&$#cCdshsYGy4qQQxBdkUd_MTt8ar``Ke@Na;59INWEtpGRsA7*~IDrmU#)_ z7_^t$SsS^_K|QDH6|C7<#EP{JU+2E2ErU3zFk^*g>-660@z#nvFV)(jwC7OP1Y7H? z^g7And4+E^WN@X6W{3rQg<6Bs{(7EQ>vF{s0QwS=9J%l+lg4O1hknx7*mCq9mb)Ze zMw|lV7wB5#J+Q?08@BkYndL(~->q$|o^k=C<@AXb!)GE=!&Oz1shDxG;CxAz$2bS8 zy{Cm!t0aR{p}ji8@H{umH&z|x&&gb`XoOg>aUq-6w7|0CHNA+9@EazZ$3ZVG^^g$3?j$&9?ydcvw(P@wT^U4H^PH zwQ_78DzEWfC!iba=U`7e*eaP@KG-+^X^f}q#xw3ZS#rdtt*g#P{Q&wm8&y0oZdV)l zo_VjQwDT1oQ1{Bas;+%u?Qe17HXo_jdWQX;^optm5t$C+wb!{qovOaRoNu#aGQ;B}H`Trfsw-mV{Gfkvw*7P@Ju zOd*c7c->x;=~f-98CrSWJgjswV>zj+`A?PK;g)BvvRJUMRmW3l>scCmGW4hu+-2U|7#&S>Z=HpRhg$(GY<4m@7BKBp^}rK;hOaUQ z9rt_d6ef6yhv*}21Ur3G;j{!&)4jHY?-FwtFAgmO==Q!V&Sdgt&dXu zS*z^x(Vw!_936B5RX9mW)6^7m#kca`z3j8nlnWS*)T|uC?+bEk{-c<`(*H2V$Bx~f z6;?dq!A1#B&>hs#ByK7i&NIuZXE`G8WfQu}OfL(Mpnv#=pPq$>kKHWXnpV`2Hl1&x zLLbOmWDXnnRlbnFXh?^;E3@i>B5IS|Jv|$?yD#qr!sCUv@FUxoUTyPdZIjmf3p7ja>4pY4W1a^kxxM_8D4QJHx6hK{>YG4%=kCsmlt&Lum_{3f3`B z7!@u4MkI_C8xLBs=EG^5LR#kamQo%TY8eZ**6BDEkNWyGvhsI>rp2x@qjSw8SQm20 zG-9beX4$K!R6Rfki_5D|sl|t@bbp_vHPdm8wdlQR4BV&1$fJK9V;Rxtps&L$@Q-hu z`SAE^`X``LnPqEdMu}{T^`GU6i9k110Wfm)jD3*(jAQcZC zPxqsFg4b}NHAi+a**|_hM_V0fv`~*0A)5_T|M*I1X`ze25zkW zh)Y&#yJ*f_3*0O^8cQARt-h{;PS9@#pshmuGqZ_|`Z>eO>sJq|A*BkHKuR!f#!i2` zt~jhWW#0Z8xjcJ#eMJe748Au4!8AJ5}Oa_6-@lj(d^OC%L@+9hdG zdfHZl%fQV`<>@);5iA?k$)*>?d-0@pC*})i6^tA6d?sFRFWy_E2MSNeo&~$2RpLC; zM`s?pyvOXuPIG-AE1*7ohmo1W5Cv<;@m-!fRsNW%hOhTrz2wMkUF24st~D6W4VsS zWoY>oZYOOS!ZXc?W(USgDhttdIXQUD(o9d2z4Gb1uo~L(A&PaZd@6u2jOQzIp7GOI zt>v1FzTV;XdQP{~0ll%dN>^T6U)2Y`pw<&PMJas*do;z?+f*^*i7Zw=*!YSS(x~Uz znIG57quf5x2VeE7@Ba(tz`Ly#KZ57rqS-zXCZu@|Js0+HF@o#0fwZ2Uv=pxvs zuPT+}k!L~wu>N=Y?1&c>j^e1YmjYx@_p-phBL9c=52C^U;lpkIllY0BJ>5TBklo_4 zh1RyvNhH1q_N-q|9_8Ojc8<@E3`pmgiJp@$yeC&{fl6EJ5(9GblgqKn z9|?OlJYd<8p=Q+6KCYFlA=UZ2!shSg|3AE{aZh8jlL~%>%nsT3W;I;r0i^d9FXvp{ z@Z4^*y|Fw$#7Dp`(tAv**N3k~o1a+5kA(S|Ma}3S&ywwVxQKnfZ6+_dM5>F`)74Nzm{v&p@t`Ko$vXk#iXW}>xIslKzUU+5JlahBL)kqy+<%U>mg!WGR8qu-yR_?`}tc$aE zcy3vuBw=O5noJrKcDW}RP&J9 z?ycuMa(0)U>50}jShL$|fvXb{;y6J*F--@#^EO>k2_3*DEQ!tOp!bg_@8B1(VvVc5 zbC*L$>tfNxqu@I0*Nt{2+g8Qyaer2C(>rJDMj$G8^$$~xHxfJosn*&?mUrcb*mWh# zRHu%$mMv@C$2{_1$Sr?Q*=c$sE!{XyjZc@$t*OWtPO0)E{|>?a_xPm=cA>CHOYL{& zKhc|KJPfOR4=qW69*tK3)7ed>(IKv~0w`YXfPNo`9Q1v*?fwoA&b-Cy*{9j2ACZq; z$0A1rdCc5pt{V_5Z;lU#_r^vp;}V6x(CXPNz{=-F(#DES51!(QZsqAIT6F>%`rP#a9j-E`5 zac|{OdTe*n)o!_80}FR}l`TdWS7q*>rwKe}%ogv8K1V)zneY^Y$@p?!S_~IN!2)%4YUjne)aTqr=NX! zjy@CKXkeWIaEfg6u14*B4*Geht6(BqM$fnUJf24BJsm9SyqA95`b^#A4_S^f09oc4@7$@AdY%&?{@A(r*f!zE_19pz#w(7v-hBEM5uWDyx)_Ib>-*;ToXq0JuL-8;6bkpt6RGbNvOcz?teJsQ%+i=31F$ z{ZQ4f|6kl$JKSw?IzwaE#~J9KR_hG;Ecs0OSa*h<&Q-^Cn>>%PiWijxNR8@XRtaV- zyj9nT+fDpcU-0byp{|{0KN5D2zB^-`biDhk2hTb;wmubW%Q>w%ug}=&=k>J9He<2O zmdEfjcrpu}ZohWynPVDPfZH_RRVFP`KgW8e_G8Nii=Nj!#f^NGm3PQOHd}OR1_5me z5&n@&{r{5*^;p0>K)2^;m9KT{b!Ud&m7zD<8Ale zBo^O&4)fWXjChLsJdB?!54p_BeP_E>USoPi%D3*<9Qu0*&0$gpI&=A=VOj~k(y5FUdj$95r>S|&MUPjMC*4E# z2&mC3sTIVU>!GS~;tOYVwEex}tLeMal_+gL);ud`{_`HI?(o{naw^n1+3I?ZJ!5 z4YT6^>txkcKbGTMJkQ6kaNdbpnNX3c3W`$_QYHK?4b%oL+Y`o5P9lw?} z{gBpn;9fE(6R&8;wH;&L7S)!lwpG_@rc0!^-MRDosQIjRT<69)tToFT=}NsWox}&q zPh*8G`^dXgZ6bwe=Mq#|W%b;FyXs2yy#fwc^K2#P?^YhWs4ibeW|L8l#8*%{0TC#< zDFxJLU`4`MHBEbav2bcJQuVTWtmS@1hb%RYu1$*vZR5OBT&%2CJKN}Mq_2-(p|ipx zc3>kvv-{3k6g0sBef|*gsO`Vb?=jS`U#I%|J)ZK|Yh_kbtrlKyG;jOUI=m`7yh1?+Y{HeG+-p?h3^Gjo;GtM{44 zIMweYuIJb1pxfVL=7sTQ^WLJEj_L*XVqVQNi(c3M!%*8Z2~1{wK0@m# z1K?e)ZJ*8C^A?@XTVIAqrX`f>ba;Y!9IMWvDLk-G)IQ3=KXauTJ1yR#tP`(Id@hll zM}&G`B_Uf+w)xsvzt{S6s|zevP+Z)Ubv}33bQ4*j=O=?>m0S8dZHsxY-Wu&=&qCIS zChUXjtuL$HqeRQJRFuXg;l4eVR=IGAWbCnP5Un4|jkQmP@dNHu7l;U$_4n7H}*=$(< zd92Xm^;KB~*cnb!UDbDJdae_Vv$sZ!vWvf#8nQ=g(F1YB-gny7|JS8IjTUx?4$SA` zHt@CTs$rQX?-%C=GQB{USNJ+M9mqy!c+Q7bK9-o-T8ONL9ehH{qx7?F84$^_>hy9O zE3fihZyux3bSzFZi$k~?Gy{ud{h_yM7U`6J?{tYP#@6?v<+DI~wdh})tr1JDv1DMC zLi?4)bv#3VmCyAYyMF5>u^OEVO$57Jz=ui`xkOmdeH4qNJcm5>w817KS3ut*dRB{k z7af+N+SGn?efIZ1mhHFjh&6I9k##)4_H1knPqBkVPetGEo}iIM`%4YTl}=@>SS^|y zTCdtVHcyQX&eLtF>nGXzdF5`cA75i35;;B0>nL|!As6q)BWGQCMvj>)n-{we)c2nr zp7&qrRa;G6-^eo7F79ysdA*K_7Kj<`|C62_n%^=Q$la?_+#q$d^DD2_3*YG;`&ptq z_owv1PQNNoSfu^gyg?hr(s#6b>v69;;j6tv9y3v$4K@+ELhAJ141FuQL1iKGOzp6h zUWvj~IjZKU(VAAs%6^9&3b;EyAv1Lm@&r+HVTy& z7>T_$_td5T2c*=jn>VXhy((0>Mat4@(lubbRP5_0g7Zjwt}RF8%4_2sTGYOVIvWpV~=r68&hx6`U zt*$!%+j#FlYw73Q>vW#gO9@tU8rQe4bJy3k(f3OCg6-5pH_yqkvHID=k@rqc+In95 z9JMy9ui}I5->OqA%rcL3-z}rj_RbU;X%-$tJBJ^M`?bs5s`T-pn@1wl-ZV_ltWWi9 zekk^<*IBb^8MV51vR~aBb@(poIltn|dPEUh_u;xG zt3H+IP<_JD)7rHUXe@ZP&%vHWP&$t=(W(6L+a@#wefR0uB3iHPH+1y>2i@lBW**Zt zn+@4%1{nZb z%KI$5V&_Xhm%3-y@!9fieG0L8B2uH%7}a@}89EjaY`p^8im2H8p;@Y(g54#QQ7Rno zazNVGW)`lKi%faG9{ql~*vyXi2=1evqcP}fQTmyu00&z^~S?xMTg_;Ja3 z&12SDt@|ic;~-J5A#SX-=^*#W-u=1xZ9QyyZe!Pg5W~arSw7F!`kJKmV0Y%fbu^B> zlRy+*50Uk-@+)7x$3~~ldmjnff+_1E z43WEl!&dk|<d9X{^LN}^Cb7u8AB)asmGyH;AK`cnMrX##11#@UaW1&=yLxOt zKC;hes`1PVrdjBl~$|OYaVeNJ6Ypc+@98ZDyk`W9I5I%&hR5p zvD&Gw+Z$$VI%|&8d#_c;bd#l%5H+uJIipw`d zL-q)rcg-N+{omG_+B4SMP8#au5eqz2Yf9s_Za%`+)Z}bRr7xN*IY<5$s$|c2H`Y|w zjX(rnQ`>%Cp*zL9>$rI5E86)J?fhBoyV?Fs34Vh*a_(?WjTfD5Q)H(#*L)}S`|5DHk5zZaD^29_`QzO{>r2Kb8IrTFP>7tUR{XAQ`5>-4yJGAoQp+gzw!X}%totsv9s2}<^wr& zKt*iLJav`N6{wX)ut=%UR!bgf&)y=Uvq3i&p7G6Ffa6}ZE~ouDmyUHcm`B9CVihf_ z^Rl?j8Wi)-UMQb^-{CtNHg9pP!7|8o4Bs==U2QV3WtQhKe5*Hhxbl2$@Jv%V`nPDs zf|*&yDzh(<~tDwu!@w909a?<=v;9u zJkP^dMv-a-?on~mg72P`xA`i-Ud!P*ddN$DLO+%`9@i`I*nJ+RlW~vDgkLzRa=~gH z;$;7gNrLVK_h(IdXS4)Vax8}ulvY3tXOJ~c8XLQZw77++2rWhIZJ#r)9mVp zeBblEK6mXLNwJt1R+dm$2t^uM)DnqPOo)y=~C3 zMovVBcCfXX%h>6L(X(v9s&8~E*!iw&{&LZC->u4O>$--cY3Uktt8-Y2Y4qOs@XFaL zC2Pi(4On$TTx?@H$T!3L)12KJ;}{}29Le{jR{BonqPf-FtOnw!yyel+DsRuWpl#`> z+_b0bqVB4$W5ZSGr4q&OvA8$Q8p)y|GkKB#B|%@O-L3ak)7U+WmkAK3yw(Bu2U`nf zuR1`pv5{Lj*Rg5_41BEEyrhDCtk|EM9rX3r!0SzVw(I|uebUyujwnmbt>zc0;^N{KotlA+i@RX$4tV5bz?s#!(l{}PyioqT3(QisOK z1sb1NmMgM`;klmT34c!JdhU-JA{M^tYA2N!fKKb+UK1H8_1$_^I<;UoweF_kEyU5Ydv7{9le9&}|`N5*^tQeE$n^}gbJ+aA}V#xXaGKqQxYhZgofje0(Jh12?phI$CG z<__&1n-09`s^_|ozC%4h0vw)~(EFnf^1LXGaooT8QR7%+SDnHMa9vV5JY=&_e!>E5 z83)Gnn)tKjUk|~TdGWg*_iP?hmusBTi@FU@EfTMQq3zYx?nr>AUL7Vn@TVOXN&z^> zte&G6oFgiZ_*2LQJf`x=#v~=10A0o<5*F;0+OOUFq*%fw(DI2>x^)e{=~Z33Z*|)8 z^h&&YmMm6^-MeC~sp&G-Zg`z4*Hk z0_~B_Iw0d}FpGTR@xQuffy1ZXVkL41EU79WTZV*+Si-$ z;hA^GSxiS|-t)rg^LLM%zaAc%mp*sib4^rrwCwsf%Jr<%NS1fpNc(f*i9FTXt6j?! z`?e00UIZE2RAg>9!N}UUc-ULB;%crQ$16MY!PsZVPlcd5d4!2h$M1FeIa+RwiJisz z{Dlr4z1p3*t|N`^{h6ox^U15*YV9q!6Nwvp)z@jgB#X`0A{hq2H~mh90dJxJ48 z^BFRoOd|0hfPC3?rE9eBdCTQtTuyJsmZQwa!%Nt=5pPHIF{Y z#yqXIc1W7&Ed%JedNLJ1dD(AS_%5*Q$Wr}oRSi30jGt;{#S-iJ%r@Tz3-2rmUVm5N zoSk321NroQ_fGkVX5$4qK3{I@cGmeUR-@6_ZotT!|7g;^C5wTIdhNb5Z5~q54YA-! zWMpdZym{QOqy4C=Tql#);v@*K8ZUfy+}-q4-=1Tu0zdr;;JNxbu{@$#)k*`EDz~q& ze{I97*sq@T83Ygef5Pp8Uwo43;T|={=VudTh3XTK76)}Q}N%%c^oUx zXRViO4RwCd@H-8wfbqe;6F2IpUT9ggIo0>=o+B?_vW{*sj%3iBEDvI&QjNw{p7GPj zvwU*pgI#a4xz)4Gb$ngdaU^Fvw8+rAIoIyjF;RW)^|h>%R(%D-SFUF7UFv*~RmR0@ zz@OQw&BjjbbWM0Bj;+U5ul*i^u927SWR2)*37R?3cfjH}KUG;CanpyV^k(ZsXI|yr z8O41ZWJn+4_2Sh|*Ue78d!4DOR;Kk>g~|i0dU%_iA0|6^EEhhz{=-d|!O5dfFedD1H(?B6J?HuN-ud?Bf`ENLj828;e8o=ts_-nG zuVdqNwr*!Sh)t);>34*~$gH%#{TRMlg*ax?A|)v{xyl$@q_{vAp8GAUfTmWS*<|Da z;14V1Nz1;6tv)QDgekP2JoEF~az@A3N3~E6;2JHP%CoW2qz86g_%L`4B8SYn*wyFf zKDQP-5k(=F*e(77o>%6&W?${xXS4788L#?t8^^9czfSfil}z4!(Xm1**s~6?WZ!#i zI=RYH#fx;|xnEm5Z$|g3qOTLq90=7tW7&P_6`9X2UgM_{Z>zOr^_0x^)@;biy$*P8 z9-;f{owoa_v6|^Q^NMBbS>iCtV=fQrSySuwo_Igz*V4mt=6E(b8!RFFV`tAP%XMBY z+=s8{W!8+^I9O~OExlecsa6kW4PDn00t$(g{s(*fPs=QR=w(WLx38(54p{abhsn+x^T#!a=Sv zq5FK=JSsm*iJc2JJxI$Z6}vi$bp-Zod)!BG+Hg`k3aWN46Ig96oVDC~-s~JvPwM}W zuLojioL0l6DyuLR4WrTA<#plF1D<_-Z2z6uRPq~VX`JDu*GR+%aFC8vjnrqu_v-#_F+?Vor#1XVBfuZu;!n7Fo-RkA#^K9eZcKvE^?)VOo z@Y=`8fX>0Og>0T8hfc0NA~`_r6mTx$9zPy5`6}uXfVbvt;v-t7Y}%-aVq}B-{h@ zyA5sxa>Z$itp<1#9E*{M>X*#y*V3|zy5&*VwvkWljqxG7r%vJMV zqu^KFODKDBUUySe$`Ri(`RUOu70b3ivhjLwLt6SlvJw(Ct##aPfy}@Ie2W#FV(8SHjZ_yI2tF9oPO^fY!1usKHyPPkTsb_J_+y&*1&E( zQpu_Bs?V46Ja?~ZOT5VE9B&v_3NC|_D%WxB zJSng8&BDiE>$T!sX!Gp+95zOZri*|+MV{}S!3y2k`oxpfhG&g#bSl~Cos;vLPA)v< zdsRlm_myMS=(zGs9%bsQ)z(MggqUinRhsfzCMp9a(K72UDUaJRWWBu70V!7)*4Pd| zjq1KVKOgt`D6f~>xaOt&Ubm;QYWYw6M)RPjYOWf$f>VLUi`6rHdPU| z>$rZow`ILW*4y)UV`uh}tPh&aT!yBTrDbkaRvkT04!YV>wHvLm^bYU#D)YV@4n*bz zV{g7l&e`GKP_vp0B3mxWlVc6PD?re%-(IiN;@ed zvC}ku(e~?1(^kz~z%y&lB>8zc>5Dw32HNYtha?YTDH z*yK>H-dwmvi@(SMV)G2W$cyqOUh}9ApNpS8|IyDHAFZFd^&Pu?93n0Oi<+Pn;yAWv zWV!I1uh?m?re%$;^VFC3d|rQUtRB%et_)G}IOe?R$GK()4soPgROKaU_I;%JHQ0>< z7G-T6zU^;4WL(6WQ35lZWR+pW0^YBtUuE7e%PgT=`Ez;^Ndmwd{vW9!AdfP5on-U^1z)cK%A3>x-}DN$>yQ1G=&J7pq%mvt zZ;sq|M&@#`$>T;H&2h}R&}hSTsB<-b>ZP-oRF%hwZmW3wb}v3lt!Wl__PM4$V~ycs zr8NX+Y|CGBv`#3_V~$F@zUin;dCgLHxqEhPuh^sd*z`JEx6`{xv#q%Dtq=8i-PS8q zp9y#N8rvXOoJv*B_tV7UMszZe=Bx9aXI4lRTXt2`t&LY@O(#p)o?@SgId&(niUeFW zzo}*!3(xq_3$Hb*t9rTS4Q_ra?Y`&ukrmQwGwwAuTys*1V3UTfV(UsSSZyck0DiaX zEs0qS`dh=>|4wEiMyzq6Ej}!tC71a;JAXb;AA8Q09Dd!t+QI2Nw9@~ZjIEzM9>uWo zbAhfqzK#<8(f?O#solVaNK$eJ_t88;t;2MD-gGZ|RaURsW>KA3X4SZG%6dZvzn8h( z_l{ccSAC$#0<;93?^WuF7y({O?@?(VtByz4I|}bZZwuXNnKk2s{eFRWNOd>VV?ujg zvf8JHET)v5f#0@Qm7m~)14waSVWU&wTP;aO znb*XZU48W_3I43UmUCnbY{({8ekwSCOpo!TFS%x>IO=mCxeACtD%c|_4zbf_?CZjH zECOsBJ5DyXn(aC7Da+N2d8rh8^P3B{+#+-xd*3ytokgj{cbjQdI&b=$DQN7EpPSvgYSVn-6Nx^F6t8K%aMD);Uo)}wHSRFQV`<;%xi~6|gs}y~- zMw5j_%!H0py02Gd6G-R+W}|d2&~%g+M}CtRFGzdKFsEr=Tqom2ctjvqoC-Ft(1zn& zv^usvqhs+v=vrUxdb!%V!P>Hj;EbmPjvX-eIu$pW^5R3rSanm; zak~jdHW{n_;`@fG8RFE!q9OBaH+akR2pgB%tJSHDCz)0qy(cvv=zz7?$$q+7{ufakW>@m2j-tU2`gb$QNE5qn+bNPZK2Ti>G!cvp|@wL2Z>nn9|Vu|DQI z=b0$qvIKdibFzpi;~}{h^ceSA{K9k6v3Ww)M>BpZvfie9mKBiFi<$lo+4i4<#uCF~ zr!fbMk8I3;D)U@bPiJzIE==l0SG6KKs*y}Mz zt@3{zdLz#aKAJ}c5)j9Fyav~2jC3;hrj1G@TmJnt2>YGgQIuXFUuRTlmXvC1a1 z3g2zrPO3;e`dJZ%D`!h*XLC46-?%N_^IdPE@!gzm0(^N z`)@(D2*xYXnum-XdYFdOuB>XAeN77pQ44ihXx&i2IOa@Oe zR}GaW0KBfxgurc_idKN<9u>Qe?wF-o?V?>bI}7i9E4ucJOZ zOT*R1Y@L2DI`+A6UE@K2KVapP+2gdF@!fZ5vga}~g;=2FmB<4ySq8^4wwj7|<+^3- zTE{nSwS;HT)5=RyJSz=Y6vcMD+3!f4yiEPgE@G?pU|YYb(32B4m$()W+B;J;y$Y|& zv+@X5g?i|qlLfqpy&ihhvcF8*@}2Xj{1zn@S|cqw`Bjf=5mJX{nadisJ885`Ua{)5 zPng6OjR5uk$$aX;dvBR1)o!+>^Z0FjR5{>d%WLv1L^HFjDmD#h%g%YI=(rSb?<<{h z@Z9`l@h*B_6!#Hq_EYta%vMU4wko_fI7l6|qQJ0ui=Bs#-{iULbXnV+pnNy;AbZ;~ z!_Mk<|BOB39(x?5XwG-krCy7^GT3-ods@GDv(jrUzM`}jo}+qgo;$vEJQvxf9ajBl z9-!Qld1D-48J$bC77>~A9jnaN^?JH&u$1z@CMNj(<*7y#K@@qWz znb2<*0n)uT%~a$%?sux{dL&;5Zo3~{w>NC-jcZBT#xEQ-zXpxu+=7A;QsD$`wTI%WSR=69Rlpw=kn36CC8$309kM&I>%Y(9|n zb`v_9w(d&28?E=CsX*h!>H)s-R1VK~nR$d~ID?gT&@oW26DjQM|98aEq`o*^zjNoP z=>~LKW?3w2U)Rp}^Vu>*Ut<_udQmxjWT)MOjZ?J*JAX6m_KHoX+LS&?q)%Lq^yI^5 zsafF3{>Uf*)L}Y@7p;kAM5@p%s%5cDW_Q$R*K8BH0A?He4#3T7teMtTzQ#}vOPt|H z@_D@1%bTYD)aRjoSUGXpzsa3+l}V~PS*$jn6Rp#IDBbu~PkD=AnN{Y#dc4^xo6p&E z0h2+0QmypKj#RSu3?{F&RN12HJi6MMyz1JHhUfkk;ohIgv7P^(Oy|F>Azh`X*f-oh z|In@>Hq^rTw7W1e)y%Zp3oC=~>&W&Xx?_c9r|EdU0}sOL`9`NPM%N9q4d}ZM^PiRB zoOwL&*)4jkHgz18o~|cG@Lb37dgk6n`Kijl>LbMFYpg0svsayNoms=zBJ+C`pVt4( zLo&N$WLc*%GaYm79W!L?mFyHkVxICAy^rWu z8@IEI0etnkzms`}uIFQ~bRN52%})K9>$S{WefnuKMb;c{L3-POBU9@L`tz6SK1;YQXStDs@LnPj_JYg>G?S_Sv2eJPI9;kZ>d<0 zX9D#pFKzF9@j0m3SkLUUGTO6Kmg`wxq2@9f$F5RDD(~+VUEgfBRdI-T1+)UKMseAD zhoz9^OP8x*H}0%F3&o92UH$NDpH1HHDz};7j6U{_2ffI?=k;{&-}#FB{`Y*N`xqrM z9IK{ELL9SD3(GDQyullC<>~r1AJDo}eb(poRVN_s`SbpJKd$FI)5XU;_KM4yVAoGw z-=BS`)&}d&YOp#}$wzaYuN#i>R=ua`XLi0;8)xDte8*`oy2 zDm>#w71bHE^NIIm^f&yr`G3UGmDU%Z55Ehrex;hB<6MrDHh=KFuWs+vAt`fg8hw3k z(N^%5%u20{6VZCL&irf1(3#k?*2I`&ABDyo#Z1UP5Gz z9>%MYD}Sci*J8P&9la~xv(%`*y80|y1!=VF<P20^)nZl$)R-lGsl3y;vxwp;Jds<-KEmkSm* z9L)ETvgxP1yuTI+kLJB*usC0z-?IP0W?kn9z#D&N`Wct!9GdS9&v({)=zQ;=kF_FQ zuU>;yn`^(3^?H5vy&klB!K&x_`PqM)Lv`GvXW}zCvBh7}8)vhZE8UOLwcggxMLoR# z7h{(jIqE0_V5`V56u6f)c}CB4R6i7*I_`A@5equAhfmw?EA2YxrOP9p#6a%3E8jtF zHq2TY^L9P=HChJ9KB8%2>6-rBP{*q4{IausJgy1L1l{V>OoE>0PhS4}S(E*qN(_zb z{7I$AEf#W*ZMr_TjJ2I^L%F%onX4I@7TPr;fFZ}>2Czq3=bG>u z*Qy2U?2Xm-^SbO@dq=>@J0hi~yjFe>`iz}?PxVmGx7O($v0BQA-UI~7ad0iKawqfd zKJZ<76=(XHg{N^3v(hI8bRJuN(3WEaLn~jg^V-!Dmh&u+SjVZ_m~=PRf_cx?YpJuG z@w)%d+UEZEmrTgoD|bAJhkWI80Gn1f=GH;=Q^Ce<6skra-TSS)rPl}EJ(6Ru#4-HR zzj2+ce21^Oseg+B?NvG7bGMkTi(1o**jE08m(ek;);l=cJwGfu_Kq#vQv1J|^JLQD z*1tee-hb1GFcJXP@zU!B8=VK6w|X6MANVP~8rR7~f1YT5x#XvL@!;=nt_|}Z)NzR1 zg&(%eFZ|k7jy(K+#e6VUzS6c{p)J>nl{Q&6J|p8KcuJ=-Hkz?}?5)PTU$W%E>n3`4 zzgJ$)yECsO`mR2LW|627n9s(u>~X)FyE?5Wy`Iyq@46etSwt=XE(21*2d*tWrq6I5 z-q%jT{hHZ28C86(Rz@{8H{5G0rFUS@dYE26Asg?tWyY}Xn=0Aq>nFY{z^T^0Mv&>c z+{INH$opYmk+)Nz&ifIMz?JALP=ETH$7BtzG7oATsZk*p(DACT-nCVS4`@6XC*f1+ zRK|*ZC7C>zbJb~=`E!28$z_~=JnVPQXZ-(tuOP==dW1+;Y3HY(C0KoFKlLusu~)9| zgIYzYbV4h3P=0{F%O@TYEF#DvfxV|XR@!D8+A}GbdXSmU8hY&Y5IN_L;#)@B{!XGs zGOw}J>UVqnm1ncHM_*b-_Us!U<`2GR+1_Jj9E3;INES`+c9PdeOyx6nY&9wma9Z*F zb;{+VP8e-06?^~wA^3fZR(GmZIVNkX3ar`N8icly&_xxFB8I=qyLn3M>J*~AavrgQu z^$TBP)y1#sxZcRwl{J$_&pJ~jN;!L4#Mo7a$iCy3?Dv|s^*wQ41y*G$zAcv1;MNTp zo;$?@>9jJ^V89$|6XM5ehJ`c zzqxVL%D-!i&z5T{u`Dmx8l%aeeXKm~hUr1K+*8#7BSYf*+B6t%)&bX3o93;jGyGC5 z8%Nj2EZX{b=}u3qK$I3WjnOT8mGSVpcWaf{J0BUx)+4Rpt*8`knpW0!sa2{(XCdFo-Xx1JwoE4MPa=26~xJ6e(=lhuiJNG6Q7qo zY3mMPQ7TIi3b7kk+A2rn9Z((D(|ea`0Z0hbsD z4H`?%Z3n>WD>OP)os2L}Y4=yY1iRH(`XQ z002*;S;_jHmsf4Qa+jFqiHZfFTi!p%b_bLSfBw$h=fid^Iy&ATi>}EkPxp77kG4*9 zH#Pe>r33mcey+BS;}Xa7p51GYRkx0#(uZVC1hSU;y_H?NuO7(OvQMpoGS1Vn>hve4 zpH>a4yu!+Jn(G``@A@d_Dbrc^j;7PvZ$J5!-rvbwN3qI$tn?yqJ=ZlHu;Z>^rq7LE zyrUfvH%6V0sPkaeBy<&WhoP;4idCk%rUPv_!ca(MTt{%`ca>`yM(&X&<2?7uV-oXj zx{#_n|9L)@={eFp58nPODfsd(Sgcg?)aqL0gtM3t9$@*W!t3*F9f_uqi>7Hr)#mg7 zw`=IF|6hA=7i-yZor&#Rx2cvyOSHq-9t}s~6$n9AWQnF_*`_6#)sSV6;*n!}V%dX1 zGN#Bj*_Oqoo0MctfUpPz$kPM{CJ&RBBuEe>zyv{nAU`hwOE1X)c}S1|L4Z6&d5Rx` z!65SxCvvm%eP6AwcI|!7x%ZrN&m~*3ZlijwTK{X+s@i*>bMCq4t=bFWre|N!6D&-4 zKP=-_l%wrU#%13fFLQ>bb(xAFptE&=&#I1k)a?U2R-~(%1v+{2Xm_runr~ZEg8Y7oyw+N&R-(|I*Nvl(j z%`qxY$ePz~BM%hu`vhIyOhaaxFI&Ye7yQ-2aU_izdhc8gx-S<~d&sq$KFCtU6 zwPo_4o}7seUSz6uP5HE9h55egRj(QoerSF6pt;UJ(#q84z#Yjl!ibD=_+gZiD-CX{ zJNP-cWtq2Ert>R03WM{=Kk$?_`2LDgk|x zq3c4T-%DmlRt!Q6c`UQ%UXe;#TF7;I@QhCo;e9f$!B=@NKSv&b-Ex_uGR@J+DRn3V zxUpmY0qEqF2Aye}bt<^zq&$1Gmo5XoX2j3h$~a?i{(721ifE&vkQ!?4Y;EKkQ7)ssuIV*-N($ z-WU<-_c7Mbp_Z|pV1h1ck@!2}9|E@h2XfSq79g!{dWMmg5^|C{fuy8Gg~OQ367X&{ z@ChP)efGY((Yh^nyqx#aWh$IO$Fhnh=8N4`Ak!p?Wmp8Hbjq{!ZnaF^qAhP)6Uz%G z=-@6r*jflm=;y(cve4;GYCPw(AVW3XC-6QV03KS*4Ag^xY=wHJ5%7Ex)rJ1kcO9 z+4JvCJ3D7U*sBKIbJDi;40)R?ajaf(6oM_^iZkaXe&6@VuTw8}e?k68&E8!X=1Q9B zBW``mT1GX>&>3{CH$vCZ(DJw^f_A6!WFF^XHG#IUHpsTC*v-6x8p1ThMO>qNCzh{&{ zP^L8`G6)3&ko28@yBzY?k*D>Xj;54x@ADx%aqn@}XEct`kv2Wh(`>wS-Mm3nvg9&|H@ofC;uKBF44sD9m z9H;YT$C2h!P5c6n9(8K`+@SSzy(6s*19L{ML7ZcLAL|xoZ;%UL;Pgm{mo_)uC(l@i zjzhM4slf9*?=}-?chB@F?||QLM1Z#2*S53_l|jTYW^8%Vh%0mAB`O1&$b(N@Rx@_Lfzvq5sD=`w1c z1qg#u7|uo9iYppu3Bx?*XMDWsb1z8;Y`|06*6+8S;?=N&-UmiaT70l5k0m^S&bg`$ zyj8sMNY?;eI)tU+q6e->v*`Grv$a+`o$)_-oe$YXCBb79_QdPIae1iFEmI;H_wQWe zE8h8b>t&9rdxAIeyNu^$mUS(3It1VP8+7y3^OY3l<12q-Ev!9yr;g~QLD>LqkF!nD z5~N(GD|~lhk03ntc^&GIx8TsRJmDrhvLd(6645W!TIOkPxiaV8~>s8OseFd@3=mVWrrsW=l#ZiK|J&0Z!pFL{& zHaOamjCE*3wbSp5?sKwMT&Xj(Hw>*yX*}GaZH!Lq4jD$H%v%1r&DK^eB}r&(%5%Xh zu!FM||CQ4MjGxus>n?Hbh&7fn{1;@8v5spUw_+OP95?CihPBSQ^$dOM%4eO_E3iRs zK`gmZRkmn)_h?lgH|vAMJMDavs{l3v@Ta?zFzI4JgbbKlvAGCXQ+3rH?(9q z&sI6tb&IqziO(x%j|R9RE;9^XNL}@FA+XMUF{P5~6`#r?R>!Wmrxy1}(@NHvE;-C8 zlK=>{GJsmifL)JsjIhtyt+4h+VVAE>m$ex8jckF(TCsM1b--N#{R|Ey zMoYeb9q(z@=Q`yFD=li+S-+c!2#Re7RNdmf?@9a)E5DU_zq-*k##pI7M+~HM&Y|uI z+|^*$iC-FIzN`*t8UI&d%{t~|70jbtx7P6_tM(39EH~YNP4o%?-vfV!op^Agbj1YE z_ONNUj5J5vKb?$)(EgFTGtyBGzdVx9prEnLr9r$3wiiaboy zPr=*&8X5hW&xgd<8rn5y_w%>Kyr|Jw1J;FeWd&f|^>POg9&hi%dWk3!o#J=jGw#9; zJ@;T?%tLqqjU$7J;e3=|Z8YI!z(L>CGdvelp7_K6W7y)l7e=d=QA8Vb&2LX<*cy-l zEirD~%V%9}cVFwiIl_)lC)@2+=<$@P=cBlD%t3c-=OB3O1XMOp^Ibdfw=hZ@-9rvb zpo>O6XpT_UK~vocD+f9~hkTmwqu13>@i*YM*Mjl|1F-92PFyho%634|g@Fc`Fxq^) z2aE{7gH(dVlqy#HboakCkqUG%#@7%XO+RnJw{J$@DiAdAhPk*c;uGN3G90z3WjZ0{ zWeH^Q5@FQ!$qVZ0o}zwf!*&-wz$2a6QO;S)XU04?E%4gRr^!;XFe(fv2oi7O1b4Fe zq@ezfZ;lo!l9lIzNgn2bM>LrArzzl@zsU$PH)#RCpUO4AiL>`H{cY0cH~V*?js)SJ z(W;)8!2(%`YJDi1+mL?Xrl~3=Y=alol}?=RUEeyES=+Ne@x$gq)@zXEwc`KgaSe;I zEO`0?Ujx=cc8-uVk2*)*qarT{9kAOntlBI%8hg_+N9U#_WSft*s)(lUSJ!e$60~r*&lJA_mU~#R}4Vuw=6J|R#4eh z(gavUo@=Q`h)LhY%Cqv&JGt=T=r_G)FW;rbF!*n=L!Y!hO2i79^a6rU zPD#00xZgVet*L2(=W0l+&fdmK$O~lqE`S`b^a~vr!gZ@+Hy!l+$~Z=Q#1#Xe=w;?J zp5FDOW3Cu$gOWF`ENG?LlyN1xrNpod&7HZ}|j|b(r+N&4Hi$U;7#3 zF|Iox#K8Ib{Ib4fM~IUT8oLZyv79X~U_qXdy=D1|^YjQt+yC4jkKtbSImCFyA3c@U zw(2?&fGe5;XB_;=GYxr)?+iMx4swCBewK5F8|Hbo2r2C=SuLbv(ZTO~hOfts^Ll=j z)_iB<2-fo{!TzMr8y$Y?AP)NVep&ls{H93`@|-Ky0g6_Fo@W{9Hae)XhS}nk*~aas z_UNrwui|vU=sP^-lFbWmC_A31QI&mPn|5}}Y_RG1Wl;OCwpg44A$~GOX;7TNbzQ2U z$J}=h-pRJo^&u;n92vLkPC3m;_|fCMGOedu_!+b9@szpJYC*%C7E*4|R!13GE(3qWE9fy-gq%0p4Pq%LHWSaR15WP6 z2^E&*C3i2*v}FbQxqDmcO-){{T^g>tgAy?tb}Ow8s3k0_W)+Zl4A;rIdmi>$4Qjg) z(0$uM*Kb>s*Ah9`h$0{(&Y3iHm&Ws4e9Pr7 z-@b3Srh;!AdJ=1N$qx*)TnZ45j5#5OJQ2@r$YTvUNRr9o-U@04l`TNXQ5wCk9Z1be zs^XO?;k3l5fOsFj^50CXFrVA#u@-pbsEtmqJ~u4GeQdnTWyn(&z%~_eo#(C-__ z>249MhR1Vr1p#B>DX%fsl2!hHtZ^8TxNvw5)N2f;Ppy#B-PT_$6E5#CK52w!jap z6Q^Itp|$6{HlF#?0gZCDV;#$MJ7w0j9wGV>+VmjJ_1zcfk^-B27G%_3=+@wsfRH~Y z3z~HzQ<|J~&;Q}es!2&jSqE4eE;AV(F}GLA#=J>6PeV%D;u@Egrkx-)>F*Yu9?#` zUYc)aDLKQ^;!#|IYX!ki`(+P}o*mGBN`sF2DQogckBTIqlRi7O$9rhhp`D$wuCw2s zIdr`OX}=7iNw3b*uxF=y;@rTAwClOBT`pzB3XlDi#@t>B*MqW~di@wD#rfB2Tt(Fc zo(1b%T}Lw3Oudy`R$U)+Wl|b6eT2L|p;t<(dh-126{}kZPX#zfj>v&~$GW~f6U)?T zmJj@*yE112d$7>GO}GbM%(vG#LC#isG-X;u;nnYQ;2Uq-@rds?)MlIUcOSshgdfrh z2H>Vs6;yIcgN{1o+0wQQWf^Mn2&j40T*r;>)%X1TrEMst+-x(pF)PL>eqBM(9jo*3 z=^2uckcW^=dA2OgI?Y)C-Qm;>A-z}skzMw|P8lK&XR_&}Y*FsJX7+r)SyytWHPx$s zYmzM!cD&5BHO)C;r?nMa!y0)PK#rJS1gB;R(((dG>6Dk+imXgMI$IPSvW_rn(`831=)rvo!5Qyw0Ob z2i=jh+>uggx&hl>E~)JQ1ZK`5Iq&=uVja)6pw&hbgnJkEjZoQUu9FuI&>Dv1C9pgvlzeH> zbHcb*Q8syc`uJ@5srv=xp_P53kxyHb`yu%C5#2&?XUD|n*%nd`j$<{_!u8GcD9bgr=8-V@jPGsEi=X{yf!)FmQgmI zzcNp?2X9~(!&~?Ij`bJ&3cqVs63?!~`U=%i>;S!Dl~&uFv`r_4bCoXS1tGicE7-XO z>Rae6a5wiCbihksQ`?qh2~+YGR%^%weY%0UYjC8#qEGHP#S?y1kuuHk0Kc}rT2{?o zzmNKgE6pbp_fcQL$b}Vt$omQniTk(-?*V@HSkKO5PxZcLmFjYI9_Yk*mw;=Q_692| zdBX~NZZh0E-4^g}C-BY}M?14Z>WwBzX<4d+72u+mfO+uJ_^x*zaq&O`$_;wS+@T34xeLj^O3T;R4b(s|l( zj)DKjJCe6)o1B6H==vt&bsh_up!@X+KQ}ANR)d`Qy+n`g_kLbq=d$uU;U~|rjn(k# zi3UBzImlv;*(lZS<52@j)!~!$6>^|8dhANfY56{ey#gXf{$4wBJjFLa9I(zj70$&~ znvacFCi803V=Rs*fi%V~-r_2B{Pl*%Rs*gxpS|{a71pcKqb`woZJ9VbXSlAEdzEze zDaNm@yZcvqqX}>u+FIX;!Xn9@Y=fi<9u8l(%-RlPKayL zetzFoe=iWG)MevJGY{pHXI{VJ4m8VIRyJzWv0c{4^id9UaF#nAcWIz)yjLiogXi6o zh}U^YuS|0$;LWE!a=qb)lq$Z{7Qcn06{x1M`aJAm*S`yrtU zS+5^n;kr9^=1|M_q+KJQ9Q8&%i}eAYbLt_Owibm^0k1Q3J+_^ikflb!0QBBS#Opj3 zGC`O86f%ICn}>cteKPKd9>wdc`+hbMR^%}^=tz_oNXk2)Ye4zS-qGJy14LPz>mla` zLP^TEBz|}Qvxwy2AFqTUqUu#;gdVlg&6}fd^j@!gNN>pMTTx|LfVE1RBfEwk;k$Bk6O8@(<$PU^)HjpfGko@Ve_=*>*OsHA2F`O~%w2eCG}8%< zrwKn9^MV1m@k{}^+pn{(*G2Xuajd5xd4toiy!8GZ(BB~MM)R5Hhp%BbnZ5Oz1kE)ieTSY~W(6PA8*4gV*H+)Yfczy*4UQTRxN1-Wg6^nXoB64- zUFE62mYLFoANA`oe)A0;?4^4ujV4FnulrAO5K%o^js>&4%qy+tu7h)xJk&H7M9!so zYdN0O#Jid&FF(tn-u*ic!ai#7%N(P9(LZ`IlXG8?dsmv^*uo-e(7l)AY)g=w^nLC8 zn=yx8d-5FJIe+lUSWY;Aj?w#SK%Fse&M9kKgnVLAust*FAaE=t3uWqj(bsdxFJ8Y1 zzGR_F8;d(t?)i*8pK&j;XV)_0W)C(>i&JysfIUlyG6wRkr%HiFI%AIA4~a!bVvg5H zTh_P2%3J5H*}AO31U?B=Bf5m?g!eus+-n_jB~=740T>qBD%Uv*<}W^I3kZ6TEO2)y z^OtP}~a0ZoK>8*^4R;{<-`!>ao+F_4;gll7vUEj-n~ev!V<< zMV#&QO?g_x?Hu@|-eZQ0EIjejlfE86Fgr(t}_uPQHyOd9feEj}Ip>)Eq z6~=4)g7w128ur(L@3`6zVaH2ESc8VS_%ZL9fzFJi7kJ-gxzTMmW{?`CQ=UD^QVl-f zZmWjX3L71^y0mq?iNC$I+tmk-d#td?>q56!8ZLgF@lC6mX06QJ4&IGAYT`YJXLrnD z;}c#|97EJKY993UifJ9nye_H&=8NoW%t7xR5H!xQc6nO9&rsUg$yK$6cZ=(o^6XVI z6~d+g-E{WOcZg)i`wn}(_vq`rBDS|0k(3!a5=Sk0$c=iI*^++_Yfy3x5@>@~$Gz`| z{1UX#)#&&u|1DvAcP^Y?+qs=pp<8p#eCGfjtLP>22V@i}H%OerXN~5VZt4NrAw7Dl z)rtFmzrU+Z3l;xmjM5O z<57#83SQg#&^}K@3-7cBFZQVTLF+x2g9jQ`6Dz5hF%#U77gvnDwwID{$rjLWVBl^W z;3K-{e@DK3!MP}k+Vas_X9N?2R{-H9^6fLnzW*9wfnas0Z0X)=&|5ulbBxbM@srda zLUp$OEcy@@WF5d(HP10GV;-B<n&*I+yCUbRvf^2;X{OxZsAY*>70MKN;HbkGXy>AtB$x1i zj%TgUU%AIJjKb$mSMb{6R9wIp@ny_G8}sS>!ibyhBG>rTJoLczn%F{GX)I(atU*OI z;DoYl2--N8?J_kv0P?0pm{3U^BYS^GDDN5Qb?Xxxc#5t>BsIK_^c8QY4Wuy3w2&|e z#RV#>m@_BWs%s9kE@xS&P;N@pJ68WN3K*R3!?LVrOfZC(22Ce4evESp+4BzREyMti zj6|LR=_Tdad-qzV9^Fy;r=$b>htcxtvh`UJJZI&)^(@FM$d03K7>l~3Je|*(w6ej% zK$CaMaTLe`D1rotyQjo`^U%$2}beyO6x7m?SV0J zg|*6{kN8Q9{&x8qIV<<45l+_`*-dC=I&CDbG>ZdzYy*Pr8tG^!xSG zX?FGEg)oE-CkKqd*;kXxKHmu4|(Bl)YepS zr9Vo~s8EP}U1`NQWaO$icIQO;V$@azR;*ViXw=;}N=O%3f~LFyQaa_O)lJO*tQ8U| z&ywA{W$Kb=i(`e=3n9NL+E(#YqhI5kNjYV_^7-M*&Y6inxkaH40e%uR(Mv>VSiuCY zNc8_0t1WHng7%D$_Voz-OYrlu?n>%X`4<%~eyhgr(u;jae*Ch8h}~aE#TKw)X-& zB-ZMfJwUIgFnk}QuPxU6-koR)O@51AMOHsApS(;Pv^U zCJ#Xm@biE>-p{Z1LeB}QJ9lTaTW|F5^qQY;3oY&4D>oPdzHfu?&wlcl&%X)LI5+Q9 z=1rRDWmwzV@Gg%zan`~ajXdsH&Q-J0@ZK+&^DfZ*@R>oajq2)q4~@TJP8st(N;Gj!&LrUR(w(uB$KW^`W_;l zgL}Ug=qrQP7@63I=CJQMeQrAYcwUmuJ2c5+K3C(a9W;86h?MX5MW3J|uC6MA%0xco z)M@Te;K#g+9pjY_*fW(j>%`+O4OmG^Zt+iIk2YSS4a(bJ1g0&z5s$T^uV*$Tltp9hu|4|K^wgu2(Xy9pI7Xx1hGU&H1rTFO82B$`yfgj8#hpY++G8eOZ(lEHYs^qG zkd=S^e-bluENzRLL&ncen72N!iP)pp`HjBs)VkxU@+LBTBW2a4Os$^BxQeK9^BTxL zX!g@HOpqyw_co`Ou6O9GPs08#>kj!_@DiW2*?rxo8_>%7oO4_6FI?P@i-+8cCMbjB zWFFFC3J=g!xj!3h&7V{C$0_Kqz8-{bzDTXQICe3u_>J>H3GFRvd?UK|y!GkP6 ztY-njV-NEg!4=r40}ee4P!_HauJunJ`rW;>z*ya(io2*Ab?xgb2pRJFDg#$nlty!& z?f~)@{H9H6g$AHCgmYdo0L`~0(MqG6ChL%&WzqVSDN~y8b5c{*@9XS%*Vp|PDA(`> z-2TYt9__INKE|wUNpIN!b9B^NkI}Mm!9u;%JXPoc)$=l;5<|S-WL_9ZSD%W0+iAD0={YI*IG3xCso(yk78wZ`sr&$AF!|fv!62iV+@zB z^}k+ALIwn6S5wj6-us!(maek${XG&yrRYj@(;`;Ky@t-!k$B!}k$SGy3qBaV zKR&x_zi-|Yv_$LI*&~eF84zmTDV0_RK-AiP+jv z`X(}=O%G+coDEz{ISNUGuR7F#g)qs6`Ia{X9RmHkGOlthfp_2ITvs1qN8CcR{tctZ zm$_&a2t8`Uoww_vyi3#vGNR{sF24E$pZl*Vqf_?$PM_YfVf8Bg;k$zv!_JW0@;@XW~1SbuEy^Mm=hs`f08Wu}i2oMgCx4(lL#o+DCi7V$Gi1vW@^Z{X3R z=l0UxtHPEBANo>1DW|)CtA*PtnwW5wz89=X&xKCwf5)k$!P8H+AFW3?=!gkwUM%nlkv(sVQKir z+AsG0?zL~R?O$`ofO|=;q+`5N%@^@^OYoAAv@0;Ko~vQ+=EZxnP{SEj5_{>1i}x?B zvxnS2qeXimWCwUIZ;P1stofvxKYo=@2KX#x{Nr#X*6^GR@)>hAzI9(ryuR2u1`{L%to( zr<TYPu8jKK*G}o6Nz(WyY z{T@5YUM+CRks|`&jJMBg&;dsp@pVniw>{65|Du1zK@Y1^umo6T5qN@O(mg~kAm&Ef zag||)ueo52_x+1F;miGPzsdqU$3-}1N_$4MoL49bS=$5nTKjkHxKs8sPi zWshI^+iQ`GDvj7iIA*KZ!9GWWj%m`ZOB=4>SS`sH=xHz5qph$yOWJ&fC$PF)4Y|@F z>3jFbF+TST|Bh+Qa`&Ea#;{VE`MB;o^};DCfNS_^!JXWlP(|pR`6FTs7DeeH- zFU`N=0KTUAwCJx-QJy15{=g|Ceb8*XQTFSY)U7yk!U3=L67(DJ!v3o0FMg}+6<&L= zC&Qi}B9K?Z9CJWLR+e+tf?b7N`V*Y%HA|9fPqG3HOL4wW_dvcl+JLPtIaU2G8NXj_ zhr0>BuE!W07jfFt0IoOzO&dFd>&z3uJVDJ4>3|IxwSwZ-2xrMBu6$i7bC%9l*)fY6 znF8N*k|?u~v22Ib@hA-!4>%!yGDg9uF)}!1@CckT(jw%%Vi4w_*GAWq80h#-tnO7_ z2D#8l6Mpm=*eCY=U3gsMdQB8n1)*T%)d0l5-vumH&zJ@?Ui*C;bzG|vH92aVdGtaTdpL!RUzY$eQoQ2H)1 zW5rao)!04@Ch_g!w84mB$?MKyv%^h(=f!558qj6M4f z7wg`4&mHZrk0X{IYn}1F#-J%D!yNOAV43Z7+iM!;u7lva*LjRAq7hV`+Mj*vB+78T%h+Ud zMUx%S@RKnLMvajXQHiwz?)6grgC`nf6eR$8d!KdCho1y>Ut15k--Nazt21=O$}B@* z(x?rB(-jeTf}mdt%dBe~?vy_FEB#g0pz+T3mFkH*INiS=(oc*yBTtUH9A4=Q z>r|FHYa6JS@Ao0uYm^(_rOD&SVU2iBcXE z)-_zoCwRsJr+mn7PEpr(31z#0#*vqB^t;f3tn~;xZ^rUKE$7#1w7kY`t&`a9R#)#`Xeu4n?@uPu|2wv2YJ3+c{GGSIcGVA(vk&KfRsbJN|m!$Z2>FSbJK z#y3S{?<3DN!-alcW^0+t;5Hl9!|8>e-s^{bK9DBzJY>6I&XJeUehC*kWnNkFz+UJs zq`RiIYDnj~N~0&^)@$=5oATE5K){)vQIad)iI1LG2VG6zh4e)`n77hPSme=hhIfG?{IkYuPcHZUegG@3(h) zZ9Zf_cYg_cI6_pSuG&<9W1EvRb=&uwuH$#1mO z?N}ywU}#_R{`0d}>_z5K+Rmr-ZNoh?Mv@@!`8K$%2T|)cq0RRg%66}jZ>uW2S@!TA zn^?ON?>&5M_u6UQ5dmMl-c+N#duM(|fz^!`>rCHP-Jw1$uab_?6SN9*)BPa=($?eX zJu%m$ocA_*cRfT4*>|BQGWrMJ`zJIoUqp#Hqatmm^JLB+8lxrS%zMOLhY^w=^Q2zS z>WL>W?{#W2PQJ5mE8cOOdk=_Lx|ep%tjg8T-H=Wgw&GpGxW-Rooj^vhLKINQ%Jtld*5-X{CDn(C z&o7VQlev5Uejq!K(d#-^Tkf2zBS|ll_$R=7t$=&oU0>O#vkd8=mhmg6CLybo z_NTa(7E|+D!Vcu3gA}+vgMXFZ9?f&cj+JoCR`Han#Q`4qj*(S!$8D7x&5gc#*eo6cwRDo$1~!l5jq#) zkhfeviy^Z~zSpKSoj#|HKV>8j{`BOZw7r5@Xa$m^7kMJhqb@C-)5+j-K;GVZWT35W zhYagoQbv7F@z)|hy6d^tudy&J%X#T_ul?xziRyR{-+w%(aafld8Q87q%e&@t;ni+n zCgxeN`!Tdan7gu$euQ2P%UI_s{o~rx_SiMB3Ce@=ZuS$(&!{p6ptA?mx}XN;eD67#Z}%nU>W^*$_lU_f9Kd8>E=v||6T6Pf@BegN1QS99Xa@&k!M@>rFUhgPAA=G~%Vr zyC!KE)Uee-8}uZ;Wyq7A(D7XG26%Iyf9VIj&!YmpqL{lfW3?XMJ|CkrK4}empI_yh zOi>P5MP0^@I;hWK!x7S!Yyb|m&zNCc>GZaZ+9I|`LgO3y{L9ntUe|e!&u_ptub>aZ zy~epZ)T!5nE1{Js!rtxsk32`F6~lb-ZQ`64MeKg(H>mSj^a@XA>`L_st=Bd<->2jK z>eDW@h77E8TxZue`*W@Oeavr7|MKMc%I)3le)fs#Oc=OU7dUzAyLhks!*}j$ zCF|Um-WeO|-WTnD=LoNM9bOI_*_QY^qi~<)fB}@LhjO&6C#j z+&XH#bPv>C4>|1f1jt$W0}x*2exJIorEJw@JyGwFxRxsc>M`8c|DZp=qLSXd>{8d; zI3f8D|M~97m5tW$VY#pOUQpLwP-F1()K;J%3*x2Cy$YRQcYA)NJnNyF0AI{iqkez$ z1OEKlt58}M78MN|WgfmhU$5QyHSB%aqRQkwJ}sQ@%p&# zN3Q8^Bq^68-h~v_W>Sq@t5&a8VdkYlIpYC&H=?}r)XxvjkJs6bh*o*`sPnDNk(kf* zSJaeQ3@k~Wd4r73B=qyc@_dRYH`Q{?jCja6r-C_ga16T@(1{;%*WGIdyRdNs*5}tB zfB1Z=9fNoEyc)g!toQM{pVrjz8L%{OqXHL}hFiN{x}y!_)@^Iu&-sV#`83bj zJ7U5U(4EOx6;vuTj&=Uio;@4yJ`jm%iU#`zpJ@F{_I$c&9Y9mvuxAQt@({g>d2YRm zdjDa0K4rD)q^=tK8mGZ6aNaup^XZ}jy%c}^h*sJVGKK8Me3JcaXRm!Ghr7=g=kz#c`` z^`U#?yASlN*YJQV>c}mwBb8L#??OrgbK@a>E?3bhC$so{g?z=|+{n$RvM3Q{ooS+H z%nNuJt~F0(#;R)<@d`YkWHHB2#wZO+vQAUVvzO7jGnZA!IaAB{xxlaX2OsN6n*fjC zZ)<*h$MtM$PA|}whk*9RD6mQ`$J*}6MFYwCjggp!Whssw{0wQ18W6bRE|v-Jrq?v< zP^QsAM2@`HeEe#EbCt1-8453REaqEAj;TW#z)h>%KOGI3zScE#NNX7p%R#LdcY!Jd z8OZ}^4md}L)z0&LrVq5}i^SLB`M0Nc+vnq1P~jN{Rf~YG3q4-e9p3+{Nr3_AC==kU z=kYqlQOSCpx+k3M_=&#x%n?6(n+G2yvZ^!9@g$Ixb%9IlW*AyU0-+4$<6z_bKJ*rNh6!2oWEpqcXz5*jB6Kc9!d5ICviW>j+O1woKUZGUPet z3_L+has@J&Z|g5b4jJ1WVXtB1hSVn09H%j_W<<kM5P z|NfS2Le6%5YMtap6CZfDFG*VI9_n$gp*<4VHGVFNtcY$vV#0lUR!?62H>)bF!lLRJ z&^2WQmv!c4cWchV&^0}7m(sc|2VU16gN}aX^Sj=U_~g}|3XnrvEr79R!ppgcx=gYj zWilpphP_w8a|RK4%kUbX@===Hysm1Ap5wDW?&J6x&_Taj?pi57I8luPjy zJRB+Z@GV$<3;Ly5KkOBP)UDfcR38lPhSQ2q?tKE-9zS7WVR??SKTyYdBagUs zn*?W)1SB_Q=ii_#m8n~^)%%tFdCdnKAR@yFd*priYX={?C|k#(xL{FMa(Kp^XRAG0 zwoy)UgYDC%Nm3C*CG?2X83O(9-F)<-h{lC+CArHKVb~R38qIV<u;H=fA)MzxLVfmS(fhA=6{XElcb47=4nr44~1qp)qE*u^S~5UXTYD7H89A zSNl|Pg4G^HY1YR)##MG6UA{Km3s$t-=DLL4d|j)HqQJI?BWM5PjGR)P9^LzO&#z%&|C5SGdPm2l>Fa^+ta+E9{Q@w)<>0^7Z$NGw7MYGii=wQhoJ3 zJM5vuU)Mq|w(08iIsDltX`A}VpJE_?)N?nnieZBi6$4P&2?7Jur~xq-AM;H;W}fX> zKj_Q8d-nUF@5-FFb7C&6HsR2R`JL@Md56z2s#V_|{(9GFw?w9(#VWSULuOmwt*XWXBmF+(7>VJ0#Id=bL8N=vXwSee4F3OnJ z?SR%_Kg-}33_#ff9y*|0L-%G!E!e~29|LRuoAaWZ-06!tcaVr4!{64f=9e-cRY3P=7pS|yW*MTC$IjVdVJKxXTTPH$zEyDbHxy}F@_#noqD_xPtR?bXGl>JP*g$W4%lfG@5aR3vVC5l z$5Dp?SUfxuak6l z?H-@zw4-yQ>F0}1C&+@&arM(^zUC=|(z0#)GoBMZcHnEw5#w0Ju}aD~WYizJ%Ss)wyX2vJE~>_O-FxzQ?~kV;pRuF5ccd%40CME$MBtR~^BQ!(kw$#iE`%(l zR~F{Gs#MA6@TzH5yZp6XAD_6=H*5?syTZyL=*p=~J+FmKopY5O=8IL}Jhw5_f|NQ? zF@I2(*G)wLnYofzyN(X`_|IYu5C4g{7g?1Sr(;#@18vB>ot9x^*S2zCE;(QOy6)?{c=q!u~ydJ&^ zb3P?Rl=VHLr~77$_u|`CDbHEi2mO!uxwwMwUDM?YaFWVfcMNiP_HocC}0 z#GJCG-v`g~fME6Carp41yTNwy?AtzRUzM#5Y7Uyuh~Bw{oD&Q}M&i%nj5MF5mSLR8 zqvHL(D_mXWjUHpzI_JdqT#=qZ&%0THC5CG+-Fg8LJkEDp9c(w`D1NRznVtt2Q~Ym>E2E3OD&b&UFcZFa&d%}!eDCyut(@DSD; zED?Ebbl0-YE?R3zLc4vQrOA))&qh634o6vQRTdr?fDeQKyK9UbMnL`B>}Zmw_X~b^K*N4;JNp$ zzh&Rn>4`nQ@fr4QkM(40?9Rz_>DJ zMnQ8W3>8m}O5|y4AGl)Yt<^OW^xSR@=)8ndkcF1>;&c;Yc5MyJp&jGJ$LWQ75A7t|4$G8eHF$` z%Ye3Sxc0d1d{CWir_K>}ecJX@MUiyI8cj=&Yb%GZzdm1_QIjWkxQ9a&iW3p_yi21w zB2~OLn((ZAn*1WK{nuD!nD968GF~&i;&*sDHs!;3OT>wIP3tnX(VU|ok;Jhbn@aeyj8l83EK%6b~X0(6~5cov3Zwz?)ZCbrN!nL zIs|=`9dT$ZDuioC28pjKR6ycyVU#vHEr&(WMI#?Hj&8jG_o$?&x|W#|=;$JF4nGUv zlkxGYw~kNr;Ek~_R_g$?$P4$dPp^yQh~+OtG#mEpPGm4`s&o7S_8jV zAy2KUA-C4Ub6$JpDNEy8`UMdr44yLu=ghM^oQvCEy@Q==?T!iuIee6WqPU{2;PE;I zy9ORTeEv-d-hJj=;cTW|RSem5AGOh(i|7O2a;95u4J~K;;%8B>rIT>}<{=A2437yE z_ttY)>aEswu%>)65R9H%0Y1>WOr0dB$RN`r1l?;%**-9 zZ}P~&&nc)4s~r2Y*Gwx`KsUeA*VIB2o%Z~VY6jaa6-+Q(L3^eQandy^<`_D84Krw^ z4cfy`#wY=akE67?JeF96izA2KCwvGxs#IPQeVs1Pq6eH&tjGeM;EApF^1H^09U!kEhWDvUboxMyp!O6{%PHGqapCYnqoyN(-WvGqjaWUbXkiqJtixi5ofb{CI5oNxV+}FCN-I7c^ak zPddtNjM@8%VO;+NIp-nzIIpc&n2YTZjy6ZS@ota$tAVow#>NP&rHa9}yG@z}!W_Ac z2i%!~3zkM7Wk_Fmr3}V`R@+?k6;Ic+iglW>O6T_XXlab(6juHM13Nq8|JCUE7Vwzh zR{OR?I9hS^ux}2asUsZhKXE?(v2(WNlImvP^m0Fgw>8Jn;v%MkSTPh^Ms0U~ZD7$2 zHC8Rd(rVD#DQH}S(+P26sFoE-)@c8Gwh@joZ^QS`f$=bgzo;!H#RigM1)ZMO`Eb6D z05ni98*8mibCsyA1Mhb~dvTwPJ+ldCo!J-c8}$e9wbxBiQznJ%HvT3%_n}95^hVPz z4dNWe{IX$-mh=1~xRzB9RGkrf-ruuFX^r044;SwxWYo^C0?4g!u}=ulwtcLlo_+EJ z*M2PLSBg^F$Kb8{bq9+v^BPXMX2%OVlV}0dCVCEsb8K2a{99Yk$+;&t>q~Ez^6!Alz|u z-P$tnJo-GSqcus;I(VdajWXk=5h^0`a^p`Q1Z~3WR}~AuXZIh&z10)AyLt+rt^Fk4 zf&2{Kd3$d6&fRpviAFaSBQN1!aL!TC0RcI`kNF61kcY9LSL9GY2i#{ z!;mtMk)S$7+B1}gbM&TL7@75F2;Zpw*tDh2pTPT@tn=sbuIjHHq1Ijmx~v#^ z3Afe!dz9tKo1ysN-5?+1dxUkUG4OM`BVXLPK22KlkTS2W0nXXHsjk+8H1#0UAhs>% z9IQO(wl~A?w>8mK4w>+p!;Cz?v6?UVRTWS*Sdn9{N#7Sy^Bw0cqFvVHpGCaW1^eXF z_{7m?aUy*Y-z@QE{B_T3{Cm*63~Z|3(e_W>Y~SnU{n*bi%IB31Xq_+a-0MwR^N=#H z?Jwk(H|>$Gmzn*%zjl;wzRG6Xi~YB4tv`zE?$daO$tNP$`FEzjHT|68oa@`BMwowKnGa}26zn!erZZf-`$#~VE?|**#=8x-c>k3@!RpN>Y*w-&_ zUZ0EBwDVTAYF4+e74m?$&Ihh_C_&?#IAJA>^(0<`*6`BoXw{m{41U1?l>W9e_9^Tr z-ru*Y=@;T^`a9F#KJLz1AFunapze2S%ZIh_YVp+{;kmtvPW%Q2q0Y>L{43^wqn`D@ zM;?ajxk+ZhZxy9h4$Fq1(TaCUtXw@OXZetYe3l2$18RrSj(DKk<^Y=xWhlK-Mw}LB zUhPwU)9#0+59{gf6N}Y9_gd|_mD`z+Cj1~mMn|~qercq?O<9iG#>RC4&-Cx*3*>^Q zs+J~)|3Mw(EN5K@r>WLVwB;@>OF0;o-YCCuZRRKM zd1oGRZPxp5yy7K9$V?fjM&K9Lx}qAC1JuZyPf^*U4EUDqdQqFk)q2!sb-gx@YIPzO z(k;7OljiMWdHcO!ZN}F{cqh`XZ#*@xacx|yai5$bQ?HS)Zs+7`%ZPF*PhEb~I`%cF zkfSUiMyH=&n;f+cDc44aFntH zI^Sn-#i;jy1GFKBkL;2IG&W|?W690GGcX*pYZkgjZFASs= z05W01=sLiyyS7bP#aA1Y9pDT3ab6lvI>37m=0>O9XzyIjprcN%%lH^a_gN)T_?IIf z#XP~qr=ImWBwHs9XG-6@tcX8@HD=`qsi){NAaLmx+J#Dp8TX%dn@yt9Mw37_ARtUK(`0R722uZ3jO4u+#I@?WyLJt5I`6uZ4XY+7F?7z4OXoAGqv7 zPChaJ9&tdOguqXMbN>GVw~Y~wzT_{5Txn2z;EqFn>da#fBij=_G!9d_YM1&nPJM5 z(=$#51n&G?sZn3?Q4T|TdAR~SJy=!7B>%NR`O8gjv^&SKyFBAl9I)4O%>1iL52n95 zC7u&}{qQloGQoGAKZ;i+zKGZQzc&4=IxYT#=|7tO^Xb2v{oc`(b;N*#uEBsdD z572>gP%1x$CEyx7QXBlo1rUSl!(MtXriAY+fEd0H`p2M+JC`yyG2B;NWAztdX}H(g zaO@r8>?`v|c#)j?v@|`-(O=5bY^yX}eBkmGP=0F5Q890!r#xL~@Bgacm-cS#7!zrn ze~_?FTWwg5>#&R5pTU%4Csb~LT&GR+|EIP%=tq1&#&rWj^Sl|#ZVmeb^xALJ-KN*P zI77jrNa9ompI$QJ%*|_qZ|4+qcABiS|A3F3X5M&0Il_%6pKVpx0nV{Wu2(H&Hf3j@ zv|)b7L$AlWlG#MR*dB5(@KfHdyk}GFnm6CNW2`|BxQHo7jDYrSxJ@om2jb!bvI96z zc{80S#ksgLR_IO8-@qv62Rm}xI9N}w4gKhp_`u`q%7<`O;a`FJn|KGA*A?D@{(#

%3x0!{11d1<)T8aUUw^K!$*t6>Wy@<|)}$ZKp_*(fcJ zZVx)r%g_bSb`ntaSO!u;rvlIChwT$8R={r4@@0~)_7!mHtYHm0;Ax(kuhO99b&}Te zyhU8lQ6Gn#bb%|T(y{?gN`_vOCI$)UiLU3jzT>U49 zC#2}P(T&SCWjG3`QKR*5Tjeo7-sNi3@@jte$0Lo9?__M%IrVreB zJMc8!eB{xo9{C%AzjykHN4^#K z`(X3$1^)i&A3pML1^(!i-(%e$nVx;m8$tiT^h@vguLJ+!^vrwy@4z3QK7RA5h9i(4 zx%oG6cAwn9?^`+_M>GkOhpYpsry*T~$^gJlHG5^`=XYkzfbJJhP z>>hZx@mk5x;{Ewoq4Ou0QT8@uzcKw0bnaasx81_o%EnjZ>os_|i*7!H|4$)`?fSne zxz}+OeH{^eV|qcE+(D#gi0Mq!=Mm{`yiUv*zXsaf=@0P#Ce2Sl|1Kn1kJpjsYtt{` zeYK|{&uCu9eD-45Mb*y!+V)t_J`AtlLKKYctBCau>c+Z%3)t)MxjClyPrribS&^3z z16Sfq`Mic$xq7ccw^i$x!1)~JzdZdWC~bw#rf;q)>bzZt&qY?u@FnPuwYJQc<-K*u z^N@QHp1zDsUIP6E;9tVO&!JAOKDP8J(HPJB@vlYpQ>bL?xjV4)JSs5PL5KY!{_#_sKaV-RZ|?W2`)BrR@6W*Nv$z+e z|EEz??!tSj?rrSTdx++Ftua^fOgs1M=uuXgopcL4cI6%QlzZW9`VC2ZGCKO}%IO72 zwVIQArp}_~HwO=|_3m%I&n_DyXgkFIKLtDY5cAVmN%q2RMa6!78u5G^r^PFv^8Xh> z`LuTP)7X3T$!xv~>?OcI#(sDnl3&A|eRwwgUGQH;EIgx_=O4mT+b>@St#u81<*Sf; z5mopWbZ=p&eg#^8h#x4{OHV)j2T*xUDx^ke z|I@NoEE(d%d5y7T(WgQZ`&{o0+EUb%hm?8V!!y>Rc&tFI%fUpo8T ztH1o4%;)Tz5hq&I@N>`qJl~4xvwd?&(*5 z8K!>fF3NW2mFNFRVLbE9tABF#@@=YpoC2Hk7}7#SuRZ_Uby|r zYqwu}`m5jmFkfc@%#&4yYtFRXMgwht1o~1-fL%n zco%E(^>3pxe{%NK+b`bw*4J+R!B<}W!{5F2`Op9Gy86TGD$Xh1U;Oa8`ort$5A1an UPeG@AIK$5$;Htj)=Y-_{ACb}WApigX literal 0 HcmV?d00001 diff --git a/files/emscripten/index.html b/files/emscripten/index.html index 99352febb69..3590631317b 100644 --- a/files/emscripten/index.html +++ b/files/emscripten/index.html @@ -3,11 +3,19 @@ fheroes2 - + + + +