diff --git a/.gitignore b/.gitignore index c7a844a..1adbe13 100644 --- a/.gitignore +++ b/.gitignore @@ -44,9 +44,6 @@ bld/ # Visual Studio 2015/2017 cache/options directory .vs/ -# Libraries (binaries that aren't in the repo) -lib/ - # Runtime files imgui.ini rt64.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b3cb045 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lib/RmlUi"] + path = lib/RmlUi + url = https://github.com/mikke89/RmlUi/ +[submodule "thirdparty/RmlUi"] + path = thirdparty/RmlUi + url = https://github.com/mikke89/RmlUi diff --git a/CMakeLists.txt b/CMakeLists.txt index e54e60e..0ab6e61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_minimum_required(VERSION 3.20) project(MMRecomp) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +# set(CMAKE_CXX_VISIBILITY_PRESET hidden) if(UNIX AND NOT APPLE) set(LINUX TRUE) @@ -10,7 +12,10 @@ endif() set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +find_package(Freetype REQUIRED) + add_subdirectory(${CMAKE_SOURCE_DIR}/../mupen_rt64/mupen64plus-video-rt64 ${CMAKE_BINARY_DIR}/rt64) +add_subdirectory(${CMAKE_SOURCE_DIR}/thirdparty/RmlUi) target_include_directories(rt64 PRIVATE ${CMAKE_BINARY_DIR}/rt64/src) get_target_property(RT64_BASENAME rt64 OUTPUT_NAME) @@ -66,6 +71,8 @@ set (SOURCES ${CMAKE_SOURCE_DIR}/rsp/aspMain.cpp ${CMAKE_SOURCE_DIR}/rsp/njpgdspMain.cpp + + ${CMAKE_SOURCE_DIR}/thirdparty/RmlUi/Backends/RmlUi_Platform_SDL.cpp ) add_executable(MMRecomp) @@ -73,6 +80,8 @@ add_executable(MMRecomp) target_include_directories(MMRecomp PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/thirdparty + ${CMAKE_SOURCE_DIR}/thirdparty/RmlUi/Include + ${CMAKE_SOURCE_DIR}/thirdparty/RmlUi/Backends ${CMAKE_SOURCE_DIR}/../mupen_rt64/mupen64plus-win32-deps/SDL2-2.26.3/include ${CMAKE_SOURCE_DIR}/../mupen_rt64/mupen64plus-video-rt64/src ${CMAKE_SOURCE_DIR}/../mupen_rt64/mupen64plus-video-rt64/src/rhi @@ -94,6 +103,9 @@ target_link_libraries(MMRecomp PRIVATE RecompiledFuncs SDL2 rt64 + Freetype::Freetype + RmlCore + RmlDebugger ) # TODO fix the RT64 CMake script so that this doesn't need to be duplicated here diff --git a/MMRecomp.sln b/MMRecomp.sln deleted file mode 100644 index 938537c..0000000 --- a/MMRecomp.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33027.164 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMRecomp", "MMRecomp.vcxproj", "{14B47028-6A86-4660-A86D-2E69F229E110}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {14B47028-6A86-4660-A86D-2E69F229E110}.Debug|x64.ActiveCfg = Debug|x64 - {14B47028-6A86-4660-A86D-2E69F229E110}.Debug|x64.Build.0 = Debug|x64 - {14B47028-6A86-4660-A86D-2E69F229E110}.Debug|x86.ActiveCfg = Debug|Win32 - {14B47028-6A86-4660-A86D-2E69F229E110}.Debug|x86.Build.0 = Debug|Win32 - {14B47028-6A86-4660-A86D-2E69F229E110}.Release|x64.ActiveCfg = Release|x64 - {14B47028-6A86-4660-A86D-2E69F229E110}.Release|x64.Build.0 = Release|x64 - {14B47028-6A86-4660-A86D-2E69F229E110}.Release|x86.ActiveCfg = Release|Win32 - {14B47028-6A86-4660-A86D-2E69F229E110}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {39A9C7D9-F465-4453-BEEE-2DDC43DA95F4} - EndGlobalSection -EndGlobal diff --git a/MMRecomp.vcxproj b/MMRecomp.vcxproj deleted file mode 100644 index 75d2082..0000000 --- a/MMRecomp.vcxproj +++ /dev/null @@ -1,238 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {14b47028-6a86-4660-a86d-2e69f229e110} - MMRecomp - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Makefile - true - v142 - Unicode - - - Makefile - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - make CONFIG=$(Configuration) LIB_DIR="$(VC_LibraryPath_VC_x64_Desktop)" UCRT_DIR="$(UniversalCRT_LibraryPath_x64)" SDK_DIR="$(WindowsSDK_LibraryPath)\x64" -j$(NUMBER_OF_PROCESSORS) - make CONFIG=$(Configuration) clean - $(SolutionDir)build\$(Configuration)\ - - - false - make CONFIG=$(Configuration) LIB_DIR="$(VC_LibraryPath_VC_x64_Desktop)" UCRT_DIR="$(UniversalCRT_LibraryPath_x64)" SDK_DIR="$(WindowsSDK_LibraryPath)\x64" -j$(NUMBER_OF_PROCESSORS) - make CONFIG=$(Configuration) clean - $(SolutionDir)build\$(Configuration)\ - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - $(SolutionDir)include;$(SolutionDir)lib/SDL2-2.24.0\include;$(SolutionDir)thirdparty;%(AdditionalIncludeDirectories) - stdcpp20 - - - Console - true - $(ProjectDir)lib\RT64\$(Configuration)\RT64.lib;$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.lib;%(AdditionalDependencies) - - - XCOPY "$(ProjectDir)lib\RT64\$(Configuration)\*.dll" "$(TargetDir)" /S /Y -XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S /Y - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - $(SolutionDir)include;$(SolutionDir)lib/SDL2-2.24.0\include;$(SolutionDir)thirdparty;%(AdditionalIncludeDirectories) - stdcpp20 - - - Console - true - true - true - $(ProjectDir)lib\RT64\$(Configuration)\RT64.lib;$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.lib;%(AdditionalDependencies) - - - XCOPY "$(ProjectDir)lib\RT64\$(Configuration)\*.dll" "$(TargetDir)" /S /Y -XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S /Y - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - $(SolutionDir)include;$(SolutionDir)lib/SDL2-2.24.0\include;$(SolutionDir)thirdparty;%(AdditionalIncludeDirectories) - stdcpp20 - - - Console - true - $(ProjectDir)lib\RT64\$(Configuration)\RT64.lib;$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.lib;%(AdditionalDependencies) - - - XCOPY "$(ProjectDir)lib\RT64\$(Configuration)\*.dll" "$(TargetDir)" /S /Y -XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S /Y - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - $(SolutionDir)include;$(SolutionDir)lib/SDL2-2.24.0\include;$(SolutionDir)thirdparty;%(AdditionalIncludeDirectories) - stdcpp20 - - - Console - true - true - true - $(ProjectDir)lib\RT64\$(Configuration)\RT64.lib;$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.lib;%(AdditionalDependencies) - - - XCOPY "$(ProjectDir)lib\RT64\$(Configuration)\*.dll" "$(TargetDir)" /S /Y -XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S /Y - - - - - MaxSpeed - MaxSpeed - Default - Default - - - - - - - - - - - - - MaxSpeed - MaxSpeed - Default - Default - - - MaxSpeed - MaxSpeed - Default - Default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MMRecomp.vcxproj.filters b/MMRecomp.vcxproj.filters deleted file mode 100644 index bc3b782..0000000 --- a/MMRecomp.vcxproj.filters +++ /dev/null @@ -1,144 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index e2c966c..0000000 --- a/Makefile +++ /dev/null @@ -1,147 +0,0 @@ -CONFIG ?= Debug -LIB ?= 0 - -ifeq ($(CONFIG),Debug) -BUILD_DIR := build/Debug -FUNC_OPTFLAGS := -Og -g -fno-strict-aliasing -OPTFLAGS := -Og -g -fno-strict-aliasing -# Static C runtime linking -LIBS := -Wl,/nodefaultlib:libcmt -Wl,/nodefaultlib:ucrt -Wl,/nodefaultlib:libucrt -llibcmtd -llibvcruntimed -llibucrtd -# Dynamic -# LIBS := -Wl,/nodefaultlib:libcmt -Wl,/nodefaultlib:ucrt -Wl,/nodefaultlib:libucrt -lmsvcrtd -lvcruntimed -lucrtd -else ifeq ($(CONFIG),Release) -BUILD_DIR := build/Release -FUNC_OPTFLAGS := -O2 -g -fno-strict-aliasing -OPTFLAGS := -O2 -g -fno-strict-aliasing -else -$(error "Invalid build configuration: $(CONFIG)") -endif - -ifeq ($(OS),Windows_NT) - DYN_EXT := .dll - LIB_EXT := .lib - EXE_EXT := .exe - AR := clang++ - ARFLAGS := $(OPTFLAGS) -fuse-ld=llvm-lib -o - # Static C runtime linking - LIBS := -Wl,/nodefaultlib:libcmt -Wl,/nodefaultlib:ucrt -Wl,/nodefaultlib:libucrt -llibcmt -llibvcruntime -llibucrt - # Dynamic - # LIBS := -Wl,/nodefaultlib:libcmt -Wl,/nodefaultlib:ucrt -Wl,/nodefaultlib:libucrt -lmsvcrt -lvcruntime -lucrt - LIB_DIR ?= C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\lib\x64 - UCRT_DIR ?= C:\Program Files (x86)\Windows Kits\10\lib\10.0.22000.0\ucrt\x64; - SDK_DIR ?= C:\Program Files (x86)\Windows Kits\10\lib\10.0.22000.0\um\x64 - define mkdir - mkdir $(subst /,\\,$(1)) - endef - define rmdir - rmdir /S /Q $(subst /,\\,$(1)) - endef -else - DYN_EXT := .so - LIB_EXT := .a - EXE_EXT := - LIB_PRE := lib - AR := ar - ARFLAGS := rcs - define mkdir - mkdir -p $(1) - endef - define rmdir - rm -rf $(1) - endef -endif - -SRC_DIRS := portultra src rsp - -# Add the main folder if not building a library -ifneq ($(LIB),1) -SRC_DIRS += src/main -endif - -FUNCS_DIR := RecompiledFuncs -FUNCS_LIB := $(BUILD_DIR)/$(LIB_PRE)RecompiledFuncs$(LIB_EXT) -FUNCS_C_SRCS := $(wildcard $(FUNCS_DIR)/*.c) -FUNCS_CXX_SRCS := $(wildcard $(FUNCS_DIR)/*.cpp) - -FUNC_BUILD_DIR := $(BUILD_DIR)/RecompiledFuncs -FUNCS_C_OBJS := $(addprefix $(BUILD_DIR)/,$(FUNCS_C_SRCS:.c=.o)) -FUNCS_CXX_OBJS := $(addprefix $(BUILD_DIR)/,$(FUNCS_CXX_SRCS:.cpp=.o)) -ALL_FUNC_OBJS := $(FUNCS_C_OBJS) $(FUNCS_CXX_OBJS) - -BUILD_SRC_DIRS := $(addprefix $(BUILD_DIR)/,$(SRC_DIRS)) -C_SRCS := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c)) -CXX_SRCS := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp)) - -C_OBJS := $(addprefix $(BUILD_DIR)/,$(C_SRCS:.c=.o)) -CXX_OBJS := $(addprefix $(BUILD_DIR)/,$(CXX_SRCS:.cpp=.o)) -ALL_OBJS := $(C_OBJS) $(CXX_OBJS) - - -CC := clang -CXX := clang++ -LD := clang++ - -FUNC_CFLAGS := $(FUNC_OPTFLAGS) -c -Wno-unused-but-set-variable -FUNC_CXXFLAGS := $(FUNC_OPTFLAGS) -std=c++20 -c -FUNC_CPPFLAGS := -Iinclude - -WARNFLAGS := -Wall -Wextra -Wpedantic -Wno-gnu-anonymous-struct -CFLAGS := -ffunction-sections -fdata-sections -march=nehalem $(OPTFLAGS) $(WARNFLAGS) -c -CXXFLAGS := -ffunction-sections -fdata-sections -march=nehalem $(OPTFLAGS) $(WARNFLAGS) -std=c++20 -c -CPPFLAGS := -Iinclude -Ithirdparty - -ifeq ($(LIB),1) -TARGET := $(BUILD_DIR)/MMRecomp$(DYN_EXT) -LDFLAGS += -shared -else -TARGET := $(BUILD_DIR)/MMRecomp$(EXE_EXT) -endif - -ifeq ($(OS),Windows_NT) -LDFLAGS := -v -Wl,/OPT:REF $(OPTFLAGS) $(LIBS) -L"$(LIB_DIR:;=)" -L"$(UCRT_DIR:;=)" -L"$(SDK_DIR:;=)" lib/RT64/$(CONFIG)/mupen64plus-video-rt64.lib lib/SDL2-2.24.0/lib/x64/SDL2.lib -CPPFLAGS += -Ilib/SDL2-2.24.0/include -else -LDFLAGS := $(OPTFLAGS) -L$(BUILD_DIR) -lRecompiledFuncs -L. -lrt64 -lSDL2 -lX11 -Wl,--gc-sections -FUNC_CFLAGS += -ffunction-sections -fdata-sections -FUNC_CXXFLAGS += -ffunction-sections -fdata-sections -EXTRA_DEPS := librt64.a -endif - -default: $(TARGET) - -clean: - $(call rmdir,$(BUILD_DIR)) - -cleanfuncs: - - -$(FUNCS_CXX_OBJS) : $(BUILD_DIR)/%.o : %.cpp | $(FUNC_BUILD_DIR) - @$(CXX) $(FUNC_CXXFLAGS) $(FUNC_CPPFLAGS) $^ -o $@ - -$(FUNCS_C_OBJS) : $(BUILD_DIR)/%.o : %.c | $(FUNC_BUILD_DIR) - @$(CC) $(FUNC_CFLAGS) $(FUNC_CPPFLAGS) $^ -o $@ - -$(FUNCS_LIB): $(ALL_FUNC_OBJS) | $(BUILD_DIR) - $(AR) $(ARFLAGS) $@ $(FUNC_BUILD_DIR)/*.o - - - -$(CXX_OBJS) : $(BUILD_DIR)/%.o : %.cpp | $(BUILD_SRC_DIRS) - $(CXX) -MMD -MF $(@:.o=.d) $(CXXFLAGS) $(CPPFLAGS) $< -o $@ - -$(C_OBJS) : $(BUILD_DIR)/%.o : %.c | $(BUILD_SRC_DIRS) - $(CC) -MMD -MF $(@:.o=.d) $(CFLAGS) $(CPPFLAGS) $< -o $@ - -$(TARGET): $(FUNCS_LIB) $(ALL_OBJS) $(EXTRA_DEPS) | $(BUILD_SRC_DIRS) - $(LD) -o $@ $^ $(LDFLAGS) - -$(BUILD_SRC_DIRS) $(FUNC_BUILD_DIR) $(BUILD_DIR): - $(call mkdir,$@) - --include $(ALL_OBJS:.o=.d) - -MAKEFLAGS += --no-builtin-rules -.SUFFIXES: -.PHONY: default clean cleanfuncs - -print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true diff --git a/RecompiledFuncs.vcxproj b/RecompiledFuncs.vcxproj deleted file mode 100644 index 589f6b3..0000000 --- a/RecompiledFuncs.vcxproj +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {7bf5e3f9-c49f-4c84-ab64-7681f028cac2} - RecompiledFuncs - 10.0 - - - - StaticLibrary - true - v142 - Unicode - - - StaticLibrary - false - v142 - true - Unicode - - - StaticLibrary - true - v142 - Unicode - - - StaticLibrary - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)include;$(IncludePath) - - - false - $(SolutionDir)include;$(IncludePath) - - - true - $(Platform)\$(Configuration)\RecompFuncs\ - $(SolutionDir)include;$(IncludePath) - - - false - $(Platform)\$(Configuration)\RecompFuncs\ - $(SolutionDir)include;$(IncludePath) - - - - Level1 - true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - NotUsing - true - true - SyncCThrow - - - - - true - - - - - Level1 - true - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - NotUsing - - - true - false - - SyncCThrow - - - - - true - true - true - - - - - Level1 - true - _DEBUG;_LIB;%(PreprocessorDefinitions) - true - NotUsing - true - true - SyncCThrow - - - - - true - - - - - Level1 - true - true - true - NDEBUG;_LIB;%(PreprocessorDefinitions) - true - NotUsing - - - true - false - - SyncCThrow - - - - - true - true - true - - - - <_WildCardClCompile Include="RecompiledFuncs\*.c" /> - - - - - - \ No newline at end of file diff --git a/RecompiledFuncs.vcxproj.filters b/RecompiledFuncs.vcxproj.filters deleted file mode 100644 index 7a071dc..0000000 --- a/RecompiledFuncs.vcxproj.filters +++ /dev/null @@ -1,33912 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/LICENSE.txt b/assets/LICENSE.txt new file mode 100644 index 0000000..63ef813 --- /dev/null +++ b/assets/LICENSE.txt @@ -0,0 +1,212 @@ +The RmlUi samples include fonts that are separately licensed. They are listed +below along with their licenses. + +----------------------------------------------------------- +----------------------------------------------------------- +--- Lato --- +--- http://www.latofonts.com/ --- +--- --- +--- LatoLatin-Bold.ttf --- +--- LatoLatin-BoldItalic.ttf --- +--- LatoLatin-Italic.ttf --- +--- LatoLatin-Regular.ttf --- +----------------------------------------------------------- +----------------------------------------------------------- + +Copyright (c) 2010-2015, Łukasz Dziedzic (dziedzic@typoland.com), +with Reserved Font Name Lato. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + + +----------------------------------------------------------- +----------------------------------------------------------- +--- Noto Emoji --- +--- https://www.google.com/get/noto/ --- +--- --- +--- NotoEmoji-Regular.ttf --- +----------------------------------------------------------- +----------------------------------------------------------- + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/LatoLatin-Bold.ttf b/assets/LatoLatin-Bold.ttf new file mode 100644 index 0000000..c598c24 Binary files /dev/null and b/assets/LatoLatin-Bold.ttf differ diff --git a/assets/LatoLatin-BoldItalic.ttf b/assets/LatoLatin-BoldItalic.ttf new file mode 100644 index 0000000..c1f225a Binary files /dev/null and b/assets/LatoLatin-BoldItalic.ttf differ diff --git a/assets/LatoLatin-Italic.ttf b/assets/LatoLatin-Italic.ttf new file mode 100644 index 0000000..c61fc07 Binary files /dev/null and b/assets/LatoLatin-Italic.ttf differ diff --git a/assets/LatoLatin-Regular.ttf b/assets/LatoLatin-Regular.ttf new file mode 100644 index 0000000..bcc5778 Binary files /dev/null and b/assets/LatoLatin-Regular.ttf differ diff --git a/assets/NotoEmoji-Regular.ttf b/assets/NotoEmoji-Regular.ttf new file mode 100644 index 0000000..19b7bad Binary files /dev/null and b/assets/NotoEmoji-Regular.ttf differ diff --git a/assets/alien_small.tga b/assets/alien_small.tga new file mode 100644 index 0000000..6d7c53d Binary files /dev/null and b/assets/alien_small.tga differ diff --git a/assets/demo.rml b/assets/demo.rml new file mode 100644 index 0000000..acf79bb --- /dev/null +++ b/assets/demo.rml @@ -0,0 +1,29 @@ + + + Demo + + + + + This is a sample.
+ Wiseguy was here + +
diff --git a/assets/hello_world.png b/assets/hello_world.png new file mode 100644 index 0000000..bec0f82 Binary files /dev/null and b/assets/hello_world.png differ diff --git a/assets/high_scores_alien_1.tga b/assets/high_scores_alien_1.tga new file mode 100644 index 0000000..7225577 Binary files /dev/null and b/assets/high_scores_alien_1.tga differ diff --git a/assets/high_scores_alien_2.tga b/assets/high_scores_alien_2.tga new file mode 100644 index 0000000..025cc33 Binary files /dev/null and b/assets/high_scores_alien_2.tga differ diff --git a/assets/high_scores_alien_3.tga b/assets/high_scores_alien_3.tga new file mode 100644 index 0000000..9f832c3 Binary files /dev/null and b/assets/high_scores_alien_3.tga differ diff --git a/assets/high_scores_defender.tga b/assets/high_scores_defender.tga new file mode 100644 index 0000000..e10f946 Binary files /dev/null and b/assets/high_scores_defender.tga differ diff --git a/assets/invader.rcss b/assets/invader.rcss new file mode 100644 index 0000000..a31b02f --- /dev/null +++ b/assets/invader.rcss @@ -0,0 +1,703 @@ +@spritesheet theme +{ + src: invader.tga; + + /* For high dpi screens, designates the scaling it is intended to be shown at. */ + resolution: 1x; + + /** + The following specifies a list of sprite names and associated rectangles into the image given above. + Any sprite given here can be specified in a decorator. Their names must be globally unique. + Rectangles are specified as: x y width height. With the origin assumed to be at the top left corner. + */ + title-bar-l: 147px 0px 82px 85px; + title-bar-c: 229px 0px 1px 85px; + title-bar-r: 231px 0px 15px 85px; + + /* huditems are vertically flipped titlebars */ + huditem-l: 147px 55px 82px -55px; + huditem-c: 229px 55px 1px -55px; + huditem-r: 231px 55px 15px -55px; + + icon-help: 128px 152px 51px 39px; + icon-invader: 179px 152px 51px 39px; + icon-game: 230px 152px 51px 39px; + icon-hiscore: 281px 152px 51px 39px; + icon-waves: 332px 152px 51px 39px; + icon-flag: 336px 191px 51px 39px; + icon-lives: 383px 152px 51px 39px; + icon-score: 434px 152px 51px 39px; + + window-tl: 0px 0px 133px 140px; + window-t: 134px 0px 1px 140px; + window-tr: 136px 0px 10px 140px; + window-l: 0px 139px 10px 1px; + window-c: 11px 139px 1px 1px; + window-r: 10px 139px -10px 1px; /* mirrored left */ + window-bl: 0px 140px 11px 11px; + window-b: 11px 140px 1px 11px; + window-br: 136px 140px 10px 11px; + + button: 247px 0px 159px 45px; + button-hover: 247px 45px 159px 45px; + button-active: 247px 90px 159px 45px; + + button-inner: 259px 19px 135px 1px; + button-inner-hover: 259px 64px 135px 1px; + button-inner-active: 259px 109px 135px 1px; + + text-l: 162px 192px 14px 31px; + text-c: 176px 192px 1px 31px; + textarea: 162px 193px 145px 31px; + textarea-inner: 173px 206px 127px 10px; + + selectbox-tl: 281px 275px 11px 9px; + selectbox-t: 292px 275px 1px 9px; + selectbox-tr: 294px 275px 11px 9px; + selectbox-l: 281px 283px 11px 1px; + selectbox-c: 292px 283px 1px 1px; + selectbox-bl: 281px 285px 11px 11px; + selectbox-b: 292px 285px 1px 11px; + selectbox-br: 294px 285px 11px 11px; + + selectvalue: 162px 192px 145px 37px; + selectvalue-hover: 162px 230px 145px 37px; + selectarrow: 307px 192px 30px 37px; + selectarrow-hover: 307px 230px 30px 37px; + selectarrow-active: 307px 268px 30px 37px; + + radio: 407px 0px 30px 30px; + radio-hover: 437px 0px 30px 30px; + radio-active: 467px 0px 30px 30px; + radio-checked: 407px 30px 30px 30px; + radio-checked-hover: 437px 30px 30px 30px; + radio-checked-active: 467px 30px 30px 30px; + + checkbox: 407px 60px 30px 30px; + checkbox-hover: 437px 60px 30px 30px; + checkbox-active: 467px 60px 30px 30px; + checkbox-checked: 407px 90px 30px 30px; + checkbox-checked-hover: 437px 90px 30px 30px; + checkbox-checked-active: 467px 90px 30px 30px; + + tableheader-l: 127px 192px 16px 31px; + tableheader-c: 143px 192px 2px 31px; + tableheader-r: 145px 192px 15px 31px; + + expand: 3px 232px 17px 17px; + expand-hover: 21px 232px 17px 17px; + expand-active: 39px 232px 17px 17px; + expand-collapsed: 3px 250px 17px 17px; + expand-collapsed-hover: 21px 250px 17px 17px; + expand-collapsed-active: 39px 250px 17px 17px; + + slidertrack-t: 70px 199px 27px 2px; + slidertrack-c: 70px 201px 27px 1px; + slidertrack-b: 70px 202px 27px 2px; + + sliderbar-t: 56px 152px 23px 23px; + sliderbar-c: 56px 175px 23px 1px; + sliderbar-b: 56px 176px 23px 22px; + sliderbar-hover-t: 80px 152px 23px 23px; + sliderbar-hover-c: 80px 175px 23px 1px; + sliderbar-hover-b: 80px 176px 23px 22px; + sliderbar-active-t: 104px 152px 23px 23px; + sliderbar-active-c: 104px 175px 23px 1px; + sliderbar-active-b: 104px 176px 23px 22px; + + sliderarrowdec: 0px 152px 27px 24px; + sliderarrowdec-hover: 0px 177px 27px 24px; + sliderarrowdec-active: 0px 202px 27px 24px; + + sliderarrowinc: 28px 152px 27px 24px; + sliderarrowinc-hover: 28px 177px 27px 24px; + sliderarrowinc-active: 28px 202px 27px 24px; + + range-track: 219px 194px 3px 32px; + range-track-inner: 220px 204px 1px 14px; + range-bar: 127px 191px 34px 32px; + range-dec: 3px 232px 17px 17px; + range-dec-hover: 21px 232px 17px 17px; + range-dec-active: 39px 232px 17px 17px; + range-inc: 3px 250px 17px 17px; + range-inc-hover: 21px 250px 17px 17px; + range-inc-active: 39px 250px 17px 17px; + + progress-l: 103px 267px 13px 34px; + progress-c: 116px 267px 54px 34px; + progress-r: 170px 267px 13px 34px; + progress-fill-l: 110px 302px 6px 34px; + progress-fill-c: 140px 302px 6px 34px; + progress-fill-r: 170px 302px 6px 34px; + gauge: 0px 271px 100px 86px; + gauge-fill: 0px 356px 100px 86px; +} + +body +{ + font-family: LatoLatin; + font-weight: normal; + font-style: normal; + font-size: 15dp; + color: white; +} + +body.window +{ + padding-top: 43dp; + padding-bottom: 20dp; + + min-width: 250dp; + max-width: 800dp; + + min-height: 135dp; + max-height: 700dp; +} + +div#title_bar +{ + z-index: 1; + + position: absolute; + top: 7dp; + left: 0; + + text-align: left; + vertical-align: bottom; +} + +div#title_bar div#icon +{ + position: absolute; + left: 15dp; + top: -4dp; + + width: 51dp; + height: 39dp; +} + + +div#title_bar span +{ + padding-left: 85dp; + padding-right: 25dp; + padding-top: 18dp; + padding-bottom: 43dp; + + vertical-align: top; + + line-height: 24dp; + font-size: 20dp; + font-weight: bold; + + font-effect: glow(1dp black); + decorator: tiled-horizontal( title-bar-l, title-bar-c, title-bar-r ); +} + +div#window +{ + width: auto; + height: 100%; + padding: 10dp 15dp; + + decorator: tiled-box( + window-tl, window-t, window-tr, + window-l, window-c, window-r, + window-bl, window-b, window-br + ); +} + +div#content +{ + z-index: 2; + + width: auto; + height: 100%; + + overflow: hidden auto; + + text-align: center; +} + + + +p +{ + text-align: left; + margin-bottom: 1em; +} + +h1 +{ + margin-left: 0.4em; + margin-bottom: 0.4em; + + text-align: left; + font-size: 16dp; + font-weight: bold; + + font-effect: glow(1dp 1dp 1dp 1dp #1117); +} + + + +input, +select +{ + margin-left: 20dp; +} + +input.submit +{ + margin-left: 0; +} + + + +button, +input.submit +{ + display: inline-block; + + width: 159dp; + height: 33dp; + padding-top: 12dp; + + font-size: 16dp; + text-align: center; + tab-index: auto; + + decorator: image(button); +} + +button:focus, +input.submit:focus +{ + font-effect: blur(3dp #fff); +} + +button:hover, +input.submit:hover +{ + decorator: image(button-hover); +} + +button:active, +input.submit:active +{ + decorator: image(button-active); +} + +input.submit:disabled +{ + decorator: image(button); + image-color: rgba(50, 150, 150, 120); + cursor: unavailable; +} + +input.text, input.password +{ + box-sizing: border-box; + height: 31dp; + padding: 11dp 10dp 0; + decorator: tiled-horizontal( text-l, text-c, auto ); /* Right becomes mirrored left */ + cursor: text; + text-align: left; +} + +textarea +{ + padding: 14dp 12dp 10dp; + decorator: ninepatch( textarea, textarea-inner, 1.0 ); + cursor: text; + text-align: left; +} + +input.text, +input.password, +select, +textarea +{ + color: #333; + font-size: 13dp; +} + +table input.text +{ + box-sizing: border-box; + width: 100%; + height: 18dp; + margin: 0; + padding: 0 5dp; + line-height: 1.0; + + border-width: 1dp; + border-color: black; + background-color: white; + + font-size: 15dp; + + decorator: none; +} + + + +select +{ + width: 175dp; + height: 37dp; +} + +select selectvalue +{ + width: auto; + margin-right: 30dp; + + height: 25dp; + padding: 12dp 10dp 0dp 10dp; + + decorator: image( selectvalue ); +} + +select selectarrow +{ + width: 30dp; + height: 37dp; + + decorator: image( selectarrow ); +} + +select:hover selectarrow +{ + decorator: image( selectarrow-hover ); +} + +select:active selectarrow, +select selectarrow:checked +{ + decorator: image( selectarrow-active ); +} + +select selectbox +{ + margin-left: 1dp; + margin-top: -7dp; + margin-bottom: -10dp; + width: 162dp; + padding: 1dp 4dp 4dp 4dp; +} + +select selectbox, +tbody +{ + decorator: tiled-box( + selectbox-tl, selectbox-t, selectbox-tr, + selectbox-l, selectbox-c, auto, /* auto mirrors left */ + selectbox-bl, selectbox-b, selectbox-br + ); +} + +select selectbox option +{ + width: auto; + padding: 3dp 0 3dp 6dp; + background: #DDDD; +} + +select selectbox option:nth-child(even), +tr:nth-child(even) +{ + background: #FFFFFFA0; +} +select selectbox option:checked +{ + font-weight: bold; +} +select selectbox option:hover +{ + background: #FF5D5D; +} + + + +input.radio, +input.checkbox +{ + width: 30dp; + height: 30dp; + + vertical-align: -11dp; +} + +input.radio +{ + decorator: image(radio); +} + +input.radio:hover +{ + decorator: image(radio-hover); +} + +input.radio:active +{ + decorator: image(radio-active); +} + +input.radio:checked +{ + decorator: image(radio-checked); +} + +input.radio:checked:hover +{ + decorator: image(radio-checked-hover); +} + +input.radio:checked:active +{ + decorator: image(radio-checked-active); +} + +input.checkbox +{ + decorator: image(checkbox); +} + +input.checkbox:hover +{ + decorator: image(checkbox-hover); +} + +input.checkbox:active +{ + decorator: image(checkbox-active); +} + +input.checkbox:checked +{ + decorator: image(checkbox-checked); +} + +input.checkbox:checked:hover +{ + decorator: image(checkbox-checked-hover); +} + +input.checkbox:checked:active +{ + decorator: image(checkbox-checked-active); +} + +input.range { + width: 200dp; + height: 32dp; + vertical-align: -12dp; +} +input.range slidertrack { + margin-top: 3dp; + height: 22dp; + image-color: #ecc; + decorator: ninepatch( range-track, range-track-inner, 1.0 ); +} +input.range sliderbar { + margin-left: -8dp; + margin-right: -7dp; + margin-top: -3dp; + width: 34dp; + height: 23dp; + decorator: image( range-bar ); +} +input.range sliderbar:hover, input.range slidertrack:hover + sliderbar { + image-color: #cc0; +} +input.range sliderbar:active, input.range slidertrack:active + sliderbar { + image-color: #c80; +} +input.range sliderarrowdec, input.range sliderarrowinc { + width: 17dp; + height: 17dp; + margin-top: 6dp; +} +input.range sliderarrowdec { decorator: image( range-dec ); } +input.range sliderarrowinc { decorator: image( range-inc ); } +input.range sliderarrowdec:hover { decorator: image( range-dec-hover ); } +input.range sliderarrowinc:hover { decorator: image( range-inc-hover ); } +input.range sliderarrowdec:active { decorator: image( range-dec-active ); } +input.range sliderarrowinc:active { decorator: image( range-inc-active ); } + +thead tr { + height: 35dp; + decorator: tiled-horizontal( tableheader-l, tableheader-c, tableheader-r ); +} +thead td { + padding-top: 11dp; +} + +tbody { + /* Margin left/right only affects the background positioning for the decorator, not the cell placement */ + margin-left: 5dp; + margin-right: 4dp; + /* Padding top/bottom adds extra spacing between the header row and the body, and between the body and table bottom */ + padding-top: 4dp; + padding-bottom: 4dp; +} +tbody tr { + margin-left: 9dp; + margin-right: 8dp; + color: black; +} + + +expand +{ + display: block; + + margin: 1dp 0 1dp 5dp; + height: 17dp; + width: 17dp; + + decorator: image( expand ); +} + +expand:hover +{ + decorator: image( expand-hover ); +} + +expand:active +{ + decorator: image( expand-active ); +} + +expand.collapsed +{ + decorator: image( expand-collapsed ); +} + +expand.collapsed:hover +{ + decorator: image( expand-collapsed-hover ); +} + +expand.collapsed:active +{ + decorator: image( expand-collapsed-active ); +} + + +scrollbarvertical +{ + margin-top: -6dp; + margin-bottom: -6dp; + margin-right: -11dp; + width: 27dp; +} + +scrollbarvertical slidertrack +{ + decorator: tiled-vertical( slidertrack-t, slidertrack-c, slidertrack-b ); +} +scrollbarvertical slidertrack:active +{ + image-color: #aaa; +} + +scrollbarvertical sliderbar +{ + margin-left: 4dp; + width: 23dp; + min-height: 46dp; + + decorator: tiled-vertical( sliderbar-t, sliderbar-c, sliderbar-b ); +} +scrollbarvertical sliderbar:hover +{ + decorator: tiled-vertical( sliderbar-hover-t, sliderbar-hover-c, sliderbar-hover-b ); +} +scrollbarvertical sliderbar:active +{ + decorator: tiled-vertical( sliderbar-active-t, sliderbar-active-c, sliderbar-active-b ); +} + +scrollbarvertical sliderarrowdec, +scrollbarvertical sliderarrowinc +{ + width: 27dp; + height: 24dp; +} +scrollbarvertical sliderarrowdec +{ + decorator: image( sliderarrowdec ); +} +scrollbarvertical sliderarrowdec:hover +{ + decorator: image( sliderarrowdec-hover ); +} +scrollbarvertical sliderarrowdec:active +{ + decorator: image( sliderarrowdec-active ); +} + +scrollbarvertical sliderarrowinc +{ + decorator: image( sliderarrowinc ); +} +scrollbarvertical sliderarrowinc:hover +{ + decorator: image( sliderarrowinc-hover ); +} +scrollbarvertical sliderarrowinc:active +{ + decorator: image( sliderarrowinc-active ); +} + +scrollbarhorizontal +{ + width: 0; + height: 0; +} + +textarea scrollbarvertical +{ + cursor: arrow; + margin: 10dp 0 4dp 0; + width: 12dp; +} +textarea scrollbarvertical slidertrack +{ + decorator: none; +} +textarea scrollbarvertical sliderbar +{ + margin-left: 2dp; + width: 10dp; + min-height: 16dp; +} +textarea scrollbarvertical sliderarrowdec, +textarea scrollbarvertical sliderarrowinc +{ + width: 0; + height: 0; +} + +textarea scrollbarhorizontal +{ + cursor: arrow; + margin-left: 7dp; + height: 12dp; +} +textarea scrollbarhorizontal sliderbar +{ + background-color: #BC0000CC; + height: 8dp; + min-width: 10dp; +} +textarea scrollbarhorizontal sliderbar:hover +{ + background-color: #B82500CC; +} +textarea scrollbarhorizontal sliderbar:active +{ + background-color: #770000CC; +} diff --git a/assets/invader.tga b/assets/invader.tga new file mode 100644 index 0000000..3223e72 Binary files /dev/null and b/assets/invader.tga differ diff --git a/assets/present.tga b/assets/present.tga new file mode 100644 index 0000000..f2c8b1b Binary files /dev/null and b/assets/present.tga differ diff --git a/assets/rml.rcss b/assets/rml.rcss new file mode 100644 index 0000000..0905b24 --- /dev/null +++ b/assets/rml.rcss @@ -0,0 +1,61 @@ +/* +* Default styles for all the basic elements. +*/ + +div +{ + display: block; +} + +p +{ + display: block; +} + +h1 +{ + display: block; +} + +em +{ + font-style: italic; +} + +strong +{ + font-weight: bold; +} + +select +{ + text-align: left; +} + +tabset tabs +{ + display: block; +} + +table { + box-sizing: border-box; + display: table; +} +tr { + box-sizing: border-box; + display: table-row; +} +td { + box-sizing: border-box; + display: table-cell; +} +col { + box-sizing: border-box; + display: table-column; +} +colgroup { + display: table-column-group; +} +thead, tbody, tfoot { + display: table-row-group; +} diff --git a/assets/window.rml b/assets/window.rml new file mode 100644 index 0000000..e368b36 --- /dev/null +++ b/assets/window.rml @@ -0,0 +1,19 @@ + diff --git a/launch.vs.json b/launch.vs.json new file mode 100644 index 0000000..6a03e49 --- /dev/null +++ b/launch.vs.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.1", + "defaults": {}, + "configurations": [ + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "MMRecomp.exe", + "name": "MMRecomp.exe", + "currentDir": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/portultra/events.cpp b/portultra/events.cpp index f58a5e5..0c6a2a3 100644 --- a/portultra/events.cpp +++ b/portultra/events.cpp @@ -177,11 +177,11 @@ void rsp_constants_init() { for (u16 index = 1; index < 512; index++) { u64 a = index + 512; u64 b = (u64(1) << 34) / a; - rspReciprocals[index] = u16(b + 1 >> 8); + rspReciprocals[index] = u16((b + 1) >> 8); } for (u16 index = 0; index < 512; index++) { - u64 a = index + 512 >> ((index % 2 == 1) ? 1 : 0); + u64 a = (index + 512) >> ((index % 2 == 1) ? 1 : 0); u64 b = 1 << 17; //find the largest b where b < 1.0 / sqrt(a) while (a * (b + 1) * (b + 1) < (u64(1) << 44)) b++; diff --git a/portultra/multilibultra.hpp b/portultra/multilibultra.hpp index b34a9fe..c2d4091 100644 --- a/portultra/multilibultra.hpp +++ b/portultra/multilibultra.hpp @@ -10,7 +10,6 @@ #if defined(_WIN32) # define WIN32_LEAN_AND_MEAN -# define NOMINMAX # include #elif defined(__ANDROID__) # include "android/native_window.h" diff --git a/shaders/InterfacePS.hlsl b/shaders/InterfacePS.hlsl index 00fcc3f..bcfc444 100644 --- a/shaders/InterfacePS.hlsl +++ b/shaders/InterfacePS.hlsl @@ -1,6 +1,11 @@ +SamplerState gSampler : register(s1, space0); +Texture2D gTexture : register(t0, space1); + void PSMain( - out float4 resultColor : SV_TARGET + in float4 iColor : COLOR, + in float2 iUV : TEXCOORD, + out float4 oColor : SV_TARGET ) { - resultColor = float4(1,0,0,1); + oColor = gTexture.SampleLevel(gSampler, iUV, 0) * iColor; } diff --git a/shaders/InterfaceVS.hlsl b/shaders/InterfaceVS.hlsl index 44e19b3..05fd649 100644 --- a/shaders/InterfaceVS.hlsl +++ b/shaders/InterfaceVS.hlsl @@ -1,10 +1,23 @@ +struct Input { + float4x4 transform; + float2 translation; +}; + +[[vk::push_constant]] +ConstantBuffer gInput : register(b0, space0); + void VSMain( - in uint vert_id : SV_VertexID, - out float4 pos : SV_Position + in float2 iPosition : POSITION, + in float4 iColor : COLOR, + in float2 iUV : TEXCOORD, + out float4 oColor : COLOR, + out float2 oUV : TEXCOORD, + out float4 oPosition : SV_Position ) { - const float2 translation = 0.1f; - const float2 size = 0.1f; - float2 extent = float2(vert_id & 1 ? 1.0f : 0.0f, vert_id & 2 ? 1.0f : 0.0f); - pos = float4(extent * size + translation, 1.0f, 1.0f); + float2 translatedPos = iPosition + gInput.translation; + oPosition = mul(gInput.transform, float4(translatedPos, 0, 1)); + + oColor = iColor; + oUV = iUV; } diff --git a/src/main/main.cpp b/src/main/main.cpp index 3fd2863..04c26b6 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -15,7 +15,6 @@ #endif #ifdef _WIN32 -#define NOMINMAX #define WIN32_LEAN_AND_MEAN #include #include "SDL_syswm.h" @@ -151,8 +150,10 @@ Multilibultra::gfx_callbacks_t::gfx_data_t create_gfx() { return {}; } +SDL_Window* window; + Multilibultra::WindowHandle create_window(Multilibultra::gfx_callbacks_t::gfx_data_t) { - SDL_Window* window = SDL_CreateWindow("Majora's Mask", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE); + window = SDL_CreateWindow("Majora's Mask", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE); if (window == nullptr) { exit_error("Failed to create window: %s\n", SDL_GetError()); diff --git a/src/ui.cpp b/src/ui.cpp index b1b1da0..511845a 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -1,7 +1,18 @@ +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include + #include "rt64_layer.h" #include "rt64_render_hooks.h" #include "rt64_render_interface_builders.h" +#include "RmlUi/Core.h" +#include "RmlUi/Debugger.h" +#include "RmlUi_Platform_SDL.h" + #include "InterfaceVS.hlsl.spirv.h" #include "InterfacePS.hlsl.spirv.h" @@ -19,78 +30,605 @@ (format) == RT64::RenderShaderFormat::DXIL ? std::size(name##BlobDXIL) : 0) #else # define GET_SHADER_BLOB(name, format) \ - ((format) == RT64::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : nullptr) + ((format) == RT64::RenderShaderFormat::SPIRV ? name##BlobSPIRV : nullptr) # define GET_SHADER_SIZE(name, format) \ ((format) == RT64::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : 0) #endif +struct UIRenderContext { + RT64::RenderInterface* interface; + RT64::RenderDevice* device; +}; + +// TODO deduplicate from rt64_common.h +void CalculateTextureRowWidthPadding(uint32_t rowPitch, uint32_t &rowWidth, uint32_t &rowPadding) { + const int RowMultiple = 256; + rowWidth = rowPitch; + rowPadding = (rowWidth % RowMultiple) ? RowMultiple - (rowWidth % RowMultiple) : 0; + rowWidth += rowPadding; +} + +struct RmlRenderInterfaceHeap : public RT64::RenderDescriptorHeapBase { + uint32_t gSampler; + + RmlRenderInterfaceHeap(const RT64::RenderSampler* linear_sampler) { + assert(linear_sampler != nullptr); + + builder.begin(); + builder.beginSet(); + gSampler = builder.addImmutableSampler(1, linear_sampler); + builder.endSet(); + builder.end(); + } +}; + +struct RmlPushConstants { + Rml::Matrix4f transform; + Rml::Vector2f translation; +}; + +struct TextureHandle { + std::unique_ptr texture; + std::unique_ptr heap; +}; + +std::vector read_file(const std::filesystem::path& filepath) { + std::vector ret{}; + std::ifstream input_file{ filepath, std::ios::binary }; + + if (!input_file) { + return ret; + } + + input_file.seekg(0, std::ios::end); + std::streampos filesize = input_file.tellg(); + input_file.seekg(0, std::ios::beg); + + ret.resize(filesize); + + input_file.read(ret.data(), filesize); + + return ret; +} + + +template +T from_bytes_le(const char* input) { + return *reinterpret_cast(input); +} + +class RmlRenderInterface_RT64 : public Rml::RenderInterface { + static constexpr uint32_t per_frame_descriptor_set = 0; + static constexpr uint32_t per_draw_descriptor_set = 1; + + static constexpr uint32_t initial_upload_buffer_size = 1024 * 1024; + static constexpr uint32_t initial_vertex_buffer_size = 512 * sizeof(Rml::Vertex); + static constexpr uint32_t initial_index_buffer_size = 1024 * sizeof(int); + static constexpr RT64::RenderFormat RmlTextureFormat = RT64::RenderFormat::B8G8R8A8_UNORM; + static constexpr uint32_t RmlTextureFormatBytesPerPixel = RenderFormatSize(RmlTextureFormat); + struct UIRenderContext* render_context_; + int scissor_x_ = 0; + int scissor_y_ = 0; + int scissor_width_ = 0; + int scissor_height_ = 0; + Rml::Matrix4f projection_mtx_ = Rml::Matrix4f::Identity(); + Rml::Matrix4f transform_ = Rml::Matrix4f::Identity(); + Rml::Matrix4f mvp_ = Rml::Matrix4f::Identity(); + std::unordered_map textures_{}; + Rml::TextureHandle texture_count_ = 0; + std::unique_ptr upload_buffer_{}; + std::unique_ptr vertex_buffer_{}; + std::unique_ptr index_buffer_{}; + std::unique_ptr nearestSampler_{}; + std::unique_ptr linearSampler_{}; + std::unique_ptr vertex_shader_{}; + std::unique_ptr pixel_shader_{}; + std::unique_ptr heap_{}; + std::unique_ptr texture_heap_builder_{}; + std::unique_ptr layout_{}; + std::unique_ptr pipeline_{}; + uint32_t upload_buffer_size_ = 0; + uint32_t upload_buffer_bytes_used_ = 0; + uint8_t* upload_buffer_mapped_data_ = nullptr; + uint32_t vertex_buffer_size_ = 0; + uint32_t index_buffer_size_ = 0; + RT64::RenderInputSlot vertex_slot_{ 0, sizeof(Rml::Vertex) }; + RT64::RenderCommandList* list_ = nullptr; + bool scissor_enabled_ = false; + std::vector> stale_buffers_{}; +public: + RmlRenderInterface_RT64(struct UIRenderContext* render_context) { + render_context_ = render_context; + + // Create the texture upload buffer, vertex buffer and index buffer + resize_upload_buffer(initial_upload_buffer_size, false); + resize_vertex_buffer(initial_vertex_buffer_size); + resize_index_buffer(initial_index_buffer_size); + + // Describe the vertex format + std::vector vertex_elements{}; + vertex_elements.emplace_back(RT64::RenderInputElement{ "POSITION", 0, 0, RT64::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, position) }); + vertex_elements.emplace_back(RT64::RenderInputElement{ "COLOR", 0, 1, RT64::RenderFormat::R8G8B8A8_UNORM, 0, offsetof(Rml::Vertex, colour) }); + vertex_elements.emplace_back(RT64::RenderInputElement{ "TEXCOORD", 0, 2, RT64::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, tex_coord) }); + + // Create a nearest sampler and a linear sampler + RT64::RenderSamplerDesc samplerDesc; + samplerDesc.minFilter = RT64::RenderFilter::NEAREST; + samplerDesc.magFilter = RT64::RenderFilter::NEAREST; + samplerDesc.addressU = RT64::RenderTextureAddressMode::CLAMP; + samplerDesc.addressV = RT64::RenderTextureAddressMode::CLAMP; + samplerDesc.addressW = RT64::RenderTextureAddressMode::CLAMP; + nearestSampler_ = render_context->device->createSampler(samplerDesc); + + samplerDesc.minFilter = RT64::RenderFilter::LINEAR; + samplerDesc.magFilter = RT64::RenderFilter::LINEAR; + linearSampler_ = render_context->device->createSampler(samplerDesc); + + // Create the shaders + RT64::RenderShaderFormat shaderFormat = render_context->interface->getCapabilities().shaderFormat; + + vertex_shader_ = render_context->device->createShader(GET_SHADER_BLOB(InterfaceVS, shaderFormat), GET_SHADER_SIZE(InterfaceVS, shaderFormat), "VSMain", shaderFormat); + pixel_shader_ = render_context->device->createShader(GET_SHADER_BLOB(InterfacePS, shaderFormat), GET_SHADER_SIZE(InterfacePS, shaderFormat), "PSMain", shaderFormat); + + + // Create the descriptor heap + heap_ = std::make_unique(linearSampler_.get()); + heap_->create(render_context->device); + + texture_heap_builder_ = std::make_unique(); + texture_heap_builder_->begin(); + texture_heap_builder_->beginSet(); + texture_heap_builder_->addTexture(0); + texture_heap_builder_->endSet(); + texture_heap_builder_->end(); + + // Create the pipeline layout + RT64::RenderPipelineLayoutBuilder layout_builder{}; + layout_builder.begin(false, true); + layout_builder.addPushConstant(0, 0, sizeof(RmlPushConstants), RT64::RenderShaderStageFlag::VERTEX); + // Add the descriptor set for descriptors changed once per frame. + layout_builder.addDescriptorSetsFromHeap(heap_->builder); + // Add the descriptor set for descriptors changed once per draw. + layout_builder.addDescriptorSetsFromHeap(*texture_heap_builder_); + layout_builder.end(); + layout_ = layout_builder.create(render_context->device); + + // Create the pipeline description + RT64::RenderGraphicsPipelineDesc pipeline_desc{}; + pipeline_desc.renderTargetBlend[0] = RT64::RenderBlendDesc::AlphaBlend(); + pipeline_desc.renderTargetFormat[0] = RT64::RenderFormat::B8G8R8A8_UNORM; // TODO: Use whatever format the swap chain was created with. + pipeline_desc.renderTargetCount = 1; + pipeline_desc.cullMode = RT64::RenderCullMode::NONE; + pipeline_desc.inputSlots = &vertex_slot_; + pipeline_desc.inputSlotsCount = 1; + pipeline_desc.inputElements = vertex_elements.data(); + pipeline_desc.inputElementsCount = uint32_t(vertex_elements.size()); + pipeline_desc.pipelineLayout = layout_.get(); + pipeline_desc.primitiveTopology = RT64::RenderPrimitiveTopology::TRIANGLE_LIST; + pipeline_desc.vertexShader = vertex_shader_.get(); + pipeline_desc.pixelShader = pixel_shader_.get(); + + pipeline_ = render_context->device->createGraphicsPipeline(pipeline_desc); + } + + void resize_upload_buffer(uint32_t new_size, bool map = true) { + // Unmap the upload buffer if it's mapped + if (upload_buffer_mapped_data_ != nullptr) { + upload_buffer_->unmap(); + } + + // If there's already an upload buffer, move it into the stale buffers so it persists until the start of next frame. + if (upload_buffer_) { + stale_buffers_.emplace_back(std::move(upload_buffer_)); + } + + // Create the new upload buffer, update the size and map it. + upload_buffer_ = render_context_->device->createBuffer(RT64::RenderBufferDesc::UploadBuffer(new_size)); + upload_buffer_size_ = new_size; + upload_buffer_bytes_used_ = 0; + if (map) { + upload_buffer_mapped_data_ = reinterpret_cast(upload_buffer_->map()); + } + else { + upload_buffer_mapped_data_ = nullptr; + } + } + + uint32_t allocate_upload_data(uint32_t num_bytes) { + // Check if there's enough remaining room in the upload buffer to allocate the requested bytes. + uint32_t total_bytes = num_bytes + upload_buffer_bytes_used_; + + if (total_bytes > upload_buffer_size_) { + // There isn't, so mark the current upload buffer as stale and allocate a new one with 50% more space than the required amount. + resize_upload_buffer(total_bytes + total_bytes / 2); + } + + // Record the current end of the upload buffer to return. + uint32_t offset = upload_buffer_bytes_used_; + + // Bump the upload buffer's end forward by the number of bytes allocated. + upload_buffer_bytes_used_ += num_bytes; + + return offset; + } + + uint32_t allocate_upload_data_aligned(uint32_t num_bytes, uint32_t alignment) { + uint32_t padding_bytes = ((upload_buffer_bytes_used_ + alignment - 1) / alignment) * alignment - upload_buffer_bytes_used_; + + return allocate_upload_data(padding_bytes + num_bytes) + padding_bytes; + } + + void resize_vertex_buffer(uint32_t new_size) { + if (vertex_buffer_) { + stale_buffers_.emplace_back(std::move(vertex_buffer_)); + } + vertex_buffer_ = render_context_->device->createBuffer(RT64::RenderBufferDesc::VertexBuffer(new_size, RT64::RenderHeapType::DEFAULT)); + vertex_buffer_size_ = new_size; + } + + void resize_index_buffer(uint32_t new_size) { + if (index_buffer_) { + stale_buffers_.emplace_back(std::move(index_buffer_)); + } + index_buffer_ = render_context_->device->createBuffer(RT64::RenderBufferDesc::IndexBuffer(new_size, RT64::RenderHeapType::DEFAULT)); + index_buffer_size_ = new_size; + } + + void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, const Rml::Vector2f& translation) override { + uint32_t vert_size_bytes = num_vertices * sizeof(*vertices); + uint32_t index_size_bytes = num_indices * sizeof(*indices); + uint32_t total_bytes = vert_size_bytes + index_size_bytes; + uint32_t index_bytes_start = vert_size_bytes; + + if (textures_.size() == 0) { + // Create a 1x1 pixel white texture as the first handle + Rml::byte white_pixel[] = { 255, 255, 255, 255 }; + Rml::TextureHandle dummy_handle; + GenerateTexture(dummy_handle, white_pixel, Rml::Vector2i{ 1,1 }); + } + + uint32_t upload_buffer_offset = allocate_upload_data(total_bytes); + //uint32_t upload_buffer_offset = 0; + //std::unique_ptr cur_upload_buffer = render_context_->device->createBuffer(RT64::RenderBufferDesc::UploadBuffer(total_bytes)); + + if (vert_size_bytes > vertex_buffer_size_) { + resize_vertex_buffer(vert_size_bytes + vert_size_bytes / 2); + } + + if (index_size_bytes > index_buffer_size_) { + resize_index_buffer(index_size_bytes + index_size_bytes / 2); + } + + // Copy the vertex and index data into the mapped upload buffer. + memcpy(upload_buffer_mapped_data_ + upload_buffer_offset, vertices, vert_size_bytes); + memcpy(upload_buffer_mapped_data_ + upload_buffer_offset + vert_size_bytes, indices, index_size_bytes); + + //uint8_t* buffer_data = reinterpret_cast(cur_upload_buffer->map()); + //memcpy(buffer_data, vertices, vert_size_bytes); + //memcpy(buffer_data + vert_size_bytes, indices, index_size_bytes); + //cur_upload_buffer->unmap(); + + // Prepare the vertex and index buffers for being copied to. + RT64::RenderBufferBarrier copy_barriers[] = { + RT64::RenderBufferBarrier::Transition(vertex_buffer_.get(), RT64::RenderBufferState::COPY_DEST), + RT64::RenderBufferBarrier::Transition(index_buffer_.get(), RT64::RenderBufferState::COPY_DEST) + }; + list_->barriers(copy_barriers, uint32_t(std::size(copy_barriers))); + + // Copy from the upload buffer to the vertex and index buffers. + list_->copyBufferRegion(vertex_buffer_->at(0), upload_buffer_->at(upload_buffer_offset), vert_size_bytes); + list_->copyBufferRegion(index_buffer_->at(0), upload_buffer_->at(upload_buffer_offset + index_bytes_start), index_size_bytes); + + //list_->copyBufferRegion(vertex_buffer_->at(0), cur_upload_buffer->at(0), vert_size_bytes); + //list_->copyBufferRegion(index_buffer_->at(0), cur_upload_buffer->at(0 + index_bytes_start), index_size_bytes); + + //stale_buffers_.emplace_back(std::move(cur_upload_buffer)); + + // Prepare the vertex and index buffers for being used for rendering. + RT64::RenderBufferBarrier usage_barriers[] = { + RT64::RenderBufferBarrier::Transition(vertex_buffer_.get(), RT64::RenderBufferState::VERTEX_AND_CONSTANT_BUFFER), + RT64::RenderBufferBarrier::Transition(index_buffer_.get(), RT64::RenderBufferState::INDEX_BUFFER) + }; + list_->barriers(usage_barriers, uint32_t(std::size(usage_barriers))); + + // TODO set scissor, viewport + //if (scissor_enabled_) { + list_->setViewports(RT64::RenderViewport{ 0, 0, float(scissor_width_), float(scissor_height_) }); + list_->setScissors(RT64::RenderRect{ 0, 0, scissor_width_, scissor_height_ }); + //} + + RT64::RenderIndexBufferView index_view{index_buffer_->at(0), index_size_bytes, RT64::RenderFormat::R32_UINT}; + list_->setIndexBuffer(&index_view); + RT64::RenderVertexBufferView vertex_view{vertex_buffer_->at(0), vert_size_bytes}; + list_->setVertexBuffers(0, &vertex_view, 1, &vertex_slot_); + list_->setGraphicsDescriptorHeap(textures_[texture].heap.get(), 0, per_draw_descriptor_set); + + RmlPushConstants constants{ + .transform = mvp_, + .translation = translation + }; + + list_->setGraphicsPushConstants(0, &constants); + + list_->drawIndexedInstanced(num_indices, 1, 0, 0, 0); + } + + void EnableScissorRegion(bool enable) override { + scissor_enabled_ = enable; + } + + void SetScissorRegion(int x, int y, int width, int height) override { + scissor_x_ = x; + scissor_y_ = y; + scissor_width_ = width; + scissor_height_ = height; + } + + bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override { + std::filesystem::path image_path{ source.c_str() }; + + if (image_path.extension() == ".tga") { + printf("Opening TGA image: %s\n", image_path.u8string().c_str()); + + std::vector file_data = read_file(image_path); + + if (file_data.empty()) { + printf(" File not found or empty\n"); + return false; + } + + // Make sure ID length is zero + if (file_data[0] != 0) { + printf(" Nonzero ID length not supported\n"); + return false; + } + + // Make sure no color map is used + if (file_data[1] != 0) { + printf(" Color maps not supported\n"); + return false; + } + + // Make sure the image is uncompressed + if (file_data[2] != 2) { + printf(" Only uncompressed tga files supported\n"); + return false; + } + + uint16_t origin_x = from_bytes_le(file_data.data() + 8); + uint16_t origin_y = from_bytes_le(file_data.data() + 10); + uint16_t size_x = from_bytes_le(file_data.data() + 12); + uint16_t size_y = from_bytes_le(file_data.data() + 14); + + // Nonzero origin not supported + if (origin_x != 0 || origin_y != 0) { + printf(" Nonzero origin not supported\n"); + return false; + } + + uint8_t pixel_depth = file_data[16]; + + if (pixel_depth != 32) { + printf(" Only 32bpp images supported\n"); + return false; + } + + uint8_t image_descriptor = file_data[17]; + + if ((image_descriptor & 0b1111) != 8) { + printf(" Only 8bpp alpha supported\n"); + } + + if (image_descriptor & 0b110000) { + printf(" Only bottom-to-top, left-to-right pixel order supported\n"); + } + + texture_dimensions.x = size_x; + texture_dimensions.y = size_y; + + create_texture(texture_handle, reinterpret_cast(file_data.data() + 18), texture_dimensions, true); + + return true; + } + + return false; + } + + bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override { + return create_texture(texture_handle, source, source_dimensions); + } + + bool create_texture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions, bool flip_y = false) { + texture_handle = texture_count_++; + std::unique_ptr texture = + render_context_->device->createTexture(RT64::RenderTextureDesc::Texture2D(source_dimensions.x, source_dimensions.y, 1, RmlTextureFormat)); + + if (texture != nullptr) { + uint32_t image_size_bytes = source_dimensions.x * source_dimensions.y * RmlTextureFormatBytesPerPixel; + + // Calculate the texture padding for alignment purposes. + uint32_t row_pitch = source_dimensions.x * RmlTextureFormatBytesPerPixel; + uint32_t row_byte_width, row_byte_padding; + CalculateTextureRowWidthPadding(row_pitch, row_byte_width, row_byte_padding); + uint32_t row_width = row_byte_width / RmlTextureFormatBytesPerPixel; + + // Calculate the real number of bytes to upload including padding. + uint32_t uploaded_size_bytes = row_byte_width * source_dimensions.y; + + // Allocate room in the upload buffer for the uploaded data. + uint32_t upload_buffer_offset = allocate_upload_data_aligned(uploaded_size_bytes, 512); + + // Copy the source data into the upload buffer. + uint8_t* dst_data = upload_buffer_mapped_data_ + upload_buffer_offset; + + if (row_byte_padding == 0) { + // Copy row-by-row if the image is flipped. + if (flip_y) { + for (uint32_t row = 0; row < source_dimensions.y; row++) { + memcpy(dst_data + row_byte_width * (source_dimensions.y - row - 1), source + row_byte_width * row, row_byte_width); + } + } + // Directly copy if no padding is needed and the image isn't flipped. + else { + memcpy(dst_data, source, image_size_bytes); + } + } + // Otherwise pad each row as necessary. + else { + const Rml::byte *src_data = flip_y ? source + row_pitch * (source_dimensions.y - 1) : source; + uint32_t src_stride = flip_y ? -row_pitch : row_pitch; + size_t offset = 0; + + for (uint32_t row = 0; row < source_dimensions.y; row++) { //(offset + increment) <= image_size_bytes) { + memcpy(dst_data, src_data, row_pitch); + src_data += src_stride; + offset += row_pitch; + dst_data += row_byte_width; + } + } + + // Prepare the texture to be a destination for copying. + list_->barriers( + RT64::RenderTextureBarrier::Transition(texture.get(), RT64::RenderTextureState::COPY_DEST)); + + // Copy the upload buffer into the texture. + list_->copyTextureRegion( + RT64::RenderTextureCopyLocation::Subresource(texture.get()), + RT64::RenderTextureCopyLocation::PlacedFootprint(upload_buffer_.get(), RmlTextureFormat, source_dimensions.x, source_dimensions.y, 1, row_width, upload_buffer_offset)); + + // Prepare the texture for being read from a pixel shader. + list_->barriers(RT64::RenderTextureBarrier::Transition(texture.get(), RT64::RenderTextureState::PIXEL_SHADER_ACCESS)); + + // Create a descriptor heap with this texture in it. + std::unique_ptr heap = texture_heap_builder_->create(render_context_->device); + heap->setTexture(0, 0, texture.get(), RT64::RenderTextureState::PIXEL_SHADER_ACCESS); + + textures_.emplace(texture_handle, TextureHandle{ std::move(texture), std::move(heap) }); + + return true; + } + + return false; + } + + void ReleaseTexture(Rml::TextureHandle texture) override { + textures_.erase(texture); + } + + void SetTransform(const Rml::Matrix4f* transform) override { + transform_ = transform ? *transform : Rml::Matrix4f::Identity(); + recalculate_mvp(); + } + + void recalculate_mvp() { + mvp_ = projection_mtx_ * transform_; + } + + void start(RT64::RenderCommandList* list, uint32_t image_width, uint32_t image_height) { + list_ = list; + list_->setPipeline(pipeline_.get()); + list_->setGraphicsPipelineLayout(layout_.get()); + list_->setGraphicsDescriptorHeap(heap_->get(), 0, per_frame_descriptor_set); + + projection_mtx_ = Rml::Matrix4f::ProjectOrtho(0.0f, static_cast(image_width), static_cast(image_height), 0.0f, -10000, 10000); + recalculate_mvp(); + + // The following code assumes command lists aren't double buffered. + // Clear out any stale buffers from the last command list. + stale_buffers_.clear(); + + // Reset and map the upload buffer. + upload_buffer_bytes_used_ = 0; + upload_buffer_mapped_data_ = reinterpret_cast(upload_buffer_->map()); + } + + void end(RT64::RenderCommandList* list) { + list_ = nullptr; + + // Unmap the upload buffer if it's mapped. + if (upload_buffer_mapped_data_) { + upload_buffer_->unmap(); + upload_buffer_mapped_data_ = nullptr; + } + } +}; + struct { + struct UIRenderContext render; struct { - std::unique_ptr layout; - std::unique_ptr vertex_shader; - std::unique_ptr pixel_shader; - std::unique_ptr pipeline; - std::unique_ptr index_buffer; - RT64::RenderIndexBufferView index_buffer_view; - } Interface; + SystemInterface_SDL system_interface; + std::unique_ptr render_interface; + Rml::Context* context; + } rml; } UIContext; +// TODO make this not be global +extern SDL_Window* window; + void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) { printf("RT64 hook init\n"); - RT64::RenderPipelineLayoutBuilder layout_builder{}; - layout_builder.begin(); + UIContext.render.interface = interface; + UIContext.render.device = device; - layout_builder.end(); - UIContext.Interface.layout = layout_builder.create(device); + // Setup RML + UIContext.rml.system_interface.SetWindow(window); + UIContext.rml.render_interface = std::make_unique(&UIContext.render); - RT64::RenderShaderFormat shaderFormat = interface->getCapabilities().shaderFormat; + Rml::SetSystemInterface(&UIContext.rml.system_interface); + Rml::SetRenderInterface(UIContext.rml.render_interface.get()); - UIContext.Interface.vertex_shader = device->createShader(GET_SHADER_BLOB(InterfaceVS, shaderFormat), GET_SHADER_SIZE(InterfaceVS, shaderFormat), "VSMain", shaderFormat); - UIContext.Interface.pixel_shader = device->createShader(GET_SHADER_BLOB(InterfacePS, shaderFormat), GET_SHADER_SIZE(InterfacePS, shaderFormat), "PSMain", shaderFormat); + Rml::Initialise(); - RT64::RenderGraphicsPipelineDesc pipeline_desc{}; + int width, height; + SDL_GetWindowSizeInPixels(window, &width, &height); + + UIContext.rml.context = Rml::CreateContext("main", Rml::Vector2i(width, height)); - pipeline_desc.renderTargetBlend[0] = RT64::RenderBlendDesc::Copy(); - pipeline_desc.renderTargetFormat[0] = RT64::RenderFormat::B8G8R8A8_UNORM; // TODO: Use whatever format the swap chain was created with.; - pipeline_desc.renderTargetCount = 1; - pipeline_desc.cullMode = RT64::RenderCullMode::NONE; - pipeline_desc.depthClipEnabled = false; - pipeline_desc.depthEnabled = false; - pipeline_desc.depthWriteEnabled = false; - pipeline_desc.depthTargetFormat = RT64::RenderFormat::D32_FLOAT; - pipeline_desc.inputSlots = nullptr; - pipeline_desc.inputSlotsCount = 0; - pipeline_desc.inputElements = nullptr; - pipeline_desc.inputElementsCount = 0; - pipeline_desc.pipelineLayout = UIContext.Interface.layout.get(); - pipeline_desc.primitiveTopology = RT64::RenderPrimitiveTopology::TRIANGLE_LIST; - pipeline_desc.vertexShader = UIContext.Interface.vertex_shader.get(); - pipeline_desc.pixelShader = UIContext.Interface.pixel_shader.get(); - - UIContext.Interface.pipeline = device->createGraphicsPipeline(pipeline_desc); - - - static const uint32_t indices[] = {0, 1, 2, 1, 3, 2}; - UIContext.Interface.index_buffer = device->createBuffer(RT64::RenderBufferDesc::IndexBuffer(sizeof(indices), RT64::RenderHeapType::UPLOAD)); + Rml::Debugger::Initialise(UIContext.rml.context); { - void* bufferData = UIContext.Interface.index_buffer->map(); - memcpy(bufferData, indices, sizeof(indices)); - UIContext.Interface.index_buffer->unmap(); + const Rml::String directory = "assets/"; + + struct FontFace { + const char* filename; + bool fallback_face; + }; + FontFace font_faces[] = { + {"LatoLatin-Regular.ttf", false}, + {"LatoLatin-Italic.ttf", false}, + {"LatoLatin-Bold.ttf", false}, + {"LatoLatin-BoldItalic.ttf", false}, + {"NotoEmoji-Regular.ttf", true}, + }; + + for (const FontFace& face : font_faces) { + Rml::LoadFontFace(directory + face.filename, face.fallback_face); + } + } + + if (Rml::ElementDocument* document = UIContext.rml.context->LoadDocument("assets/demo.rml")) { + document->Show(); } - UIContext.Interface.index_buffer_view = RT64::RenderIndexBufferView(UIContext.Interface.index_buffer.get(), sizeof(indices), RT64::RenderFormat::R32_UINT); } void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_chain_texture) { - printf("RT64 hook draw\n"); - command_list->barriers(RT64::RenderTextureBarrier::Transition(swap_chain_texture, RT64::RenderTextureState::RENDER_TARGET)); - command_list->setGraphicsPipelineLayout(UIContext.Interface.layout.get()); - command_list->setPipeline(UIContext.Interface.pipeline.get()); - command_list->setIndexBuffer(&UIContext.Interface.index_buffer_view); - command_list->drawIndexedInstanced(6, 1, 0, 0, 0); + // command_list->setGraphicsPipelineLayout(UIContext.render.layout.get()); + // command_list->setPipeline(UIContext.render.pipeline.get()); + // command_list->setIndexBuffer(&UIContext.render.index_buffer_view); + // command_list->drawIndexedInstanced(6, 1, 0, 0, 0); + + // TODO process SDL events + + int width, height; + SDL_GetWindowSizeInPixels(window, &width, &height); + + UIContext.rml.render_interface->start(command_list, width, height); + UIContext.rml.context->Update(); + UIContext.rml.context->Render(); + UIContext.rml.render_interface->end(command_list); } void deinit_hook() { diff --git a/thirdparty/RmlUi b/thirdparty/RmlUi new file mode 160000 index 0000000..d3876e6 --- /dev/null +++ b/thirdparty/RmlUi @@ -0,0 +1 @@ +Subproject commit d3876e62fb7a0aa0630272f27ac83ef1c67b01c5 diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 0000000..83dd23a --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "84df5613f71eda8a73ab08dc3041f3af7103a5b2", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://aka.ms/vcpkg-ce-default", + "name": "microsoft" + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..22fe2da --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "freetype" + ] +}