From 2f3161d701d404b3a3cb75665dfefd9826f1760a Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 23 Mar 2026 13:18:36 +0100 Subject: [PATCH] primera implementacio de postfx --- CMakeLists.txt | 62 +- Makefile | 22 +- config/assets.txt | 1 + data/shaders/postfx.frag | 144 + data/shaders/postfx.vert | 24 + source/defaults.hpp | 2 + source/director.cpp | 4 +- source/global_inputs.cpp | 50 +- source/input.hpp | 1 + source/input_types.cpp | 2 + source/input_types.hpp | 3 +- source/options.cpp | 187 + source/options.hpp | 22 +- source/rendering/opengl/opengl_shader.cpp | 522 - source/rendering/opengl/opengl_shader.hpp | 98 - source/rendering/sdl3gpu/postfx_frag_spv.h | 10341 ++++++++++++++++++ source/rendering/sdl3gpu/postfx_vert_spv.h | 1449 +++ source/rendering/sdl3gpu/sdl3gpu_shader.cpp | 720 ++ source/rendering/sdl3gpu/sdl3gpu_shader.hpp | 106 + source/rendering/shader_backend.hpp | 20 + source/screen.cpp | 211 +- source/screen.hpp | 42 +- tools/shaders/compile_spirv.sh | 44 + 23 files changed, 13306 insertions(+), 771 deletions(-) create mode 100644 data/shaders/postfx.frag create mode 100644 data/shaders/postfx.vert delete mode 100644 source/rendering/opengl/opengl_shader.cpp delete mode 100644 source/rendering/opengl/opengl_shader.hpp create mode 100644 source/rendering/sdl3gpu/postfx_frag_spv.h create mode 100644 source/rendering/sdl3gpu/postfx_vert_spv.h create mode 100644 source/rendering/sdl3gpu/sdl3gpu_shader.cpp create mode 100644 source/rendering/sdl3gpu/sdl3gpu_shader.hpp create mode 100755 tools/shaders/compile_spirv.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2237bbf..31305c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,6 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Establece la política CMP0072 para indicar cómo se debe seleccionar la implementación de OpenGL. -# En este caso, se elige la opción "GLVND", que utiliza bibliotecas modernas y modulares (libOpenGL, libGLX), -# en lugar de la biblioteca OpenGL clásica (libGL). Esto mejora la compatibilidad con drivers recientes -# y evita ambigüedades cuando se encuentran múltiples implementaciones de OpenGL en el sistema. -cmake_policy(SET CMP0072 NEW) -set(OpenGL_GL_PREFERENCE GLVND) # --- GENERACIÓN DE VERSIÓN AUTOMÁTICA --- find_package(Git QUIET) @@ -118,21 +112,61 @@ set(EXTERNAL_SOURCES # Fuentes del sistema de renderizado set(RENDERING_SOURCES - source/rendering/opengl/opengl_shader.cpp + source/rendering/sdl3gpu/sdl3gpu_shader.cpp ) # Configuración de SDL3 find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}") +# --- SHADER COMPILATION (Linux/Windows only - macOS uses Metal) --- +if(NOT APPLE) + find_program(GLSLC_EXE NAMES glslc) + + set(SHADER_VERT_SRC "${CMAKE_SOURCE_DIR}/data/shaders/postfx.vert") + set(SHADER_FRAG_SRC "${CMAKE_SOURCE_DIR}/data/shaders/postfx.frag") + set(SHADER_VERT_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/postfx_vert_spv.h") + set(SHADER_FRAG_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/postfx_frag_spv.h") + + if(GLSLC_EXE) + add_custom_command( + OUTPUT "${SHADER_VERT_H}" "${SHADER_FRAG_H}" + COMMAND "${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.sh" + DEPENDS "${SHADER_VERT_SRC}" "${SHADER_FRAG_SRC}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + COMMENT "Compilando shaders SPIR-V..." + ) + add_custom_target(shaders DEPENDS "${SHADER_VERT_H}" "${SHADER_FRAG_H}") + message(STATUS "glslc encontrado: shaders se compilarán automáticamente") + else() + if(NOT EXISTS "${SHADER_VERT_H}" OR NOT EXISTS "${SHADER_FRAG_H}") + message(FATAL_ERROR + "glslc no encontrado y headers SPIR-V no existen.\n" + " Instala glslc: sudo apt install glslang-tools (Linux)\n" + " choco install vulkan-sdk (Windows)\n" + " O genera los headers manualmente: tools/shaders/compile_spirv.sh" + ) + else() + message(STATUS "glslc no encontrado - usando headers SPIR-V precompilados") + endif() + endif() +else() + message(STATUS "macOS: shaders SPIR-V omitidos (usa Metal)") +endif() + # --- 2. AÑADIR EJECUTABLE --- add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES}) +if(NOT APPLE AND GLSLC_EXE) + add_dependencies(${PROJECT_NAME} shaders) +endif() + # --- 3. DIRECTORIOS DE INCLUSIÓN --- target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_SOURCE_DIR}/source" "${CMAKE_SOURCE_DIR}/source/external" "${CMAKE_SOURCE_DIR}/source/rendering" + "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu" "${CMAKE_BINARY_DIR}" ) @@ -155,26 +189,14 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE $<$:_DEBUG>) # Configuración específica para cada plataforma if(WIN32) target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD) - target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 mingw32 opengl32) + target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 mingw32) elseif(APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD) - target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated) set(CMAKE_OSX_ARCHITECTURES "arm64") elseif(UNIX AND NOT APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD) endif() -# Configuración común para OpenGL -if(NOT WIN32) - find_package(OpenGL REQUIRED) - if(OPENGL_FOUND) - message(STATUS "OpenGL encontrado: ${OPENGL_LIBRARIES}") - target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENGL_LIBRARIES}) - else() - message(FATAL_ERROR "OpenGL no encontrado") - endif() -endif() - # Especificar la ubicación del ejecutable set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) diff --git a/Makefile b/Makefile index c2712d5..7421a7c 100644 --- a/Makefile +++ b/Makefile @@ -114,17 +114,17 @@ APP_SOURCES := \ source/utils.cpp \ source/external/jail_audio.cpp \ source/external/gif.cpp \ - source/rendering/opengl/opengl_shader.cpp + source/rendering/sdl3gpu/sdl3gpu_shader.cpp # Includes -INCLUDES := -Isource -Isource/external -Isource/rendering -I$(DIR_BUILD) +INCLUDES := -Isource -Isource/external -Isource/rendering -Isource/rendering/sdl3gpu -I$(DIR_BUILD) # Variables según el sistema operativo ifeq ($(OS),Windows_NT) FixPath = $(subst /,\\,$1) CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -static-libgcc -Wl,-Bstatic -lpthread -Wl,-Bdynamic -Wl,-subsystem,windows -DWINDOWS_BUILD CXXFLAGS_DEBUG := -std=c++20 -Wall -g -D_DEBUG -DWINDOWS_BUILD - LDFLAGS := -lmingw32 -lws2_32 -lSDL3 -lopengl32 + LDFLAGS := -lmingw32 -lws2_32 -lSDL3 RM := del /Q MKDIR := mkdir else @@ -138,12 +138,10 @@ else UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) CXXFLAGS += -DLINUX_BUILD - LDFLAGS += -lGL endif ifeq ($(UNAME_S),Darwin) - CXXFLAGS += -Wno-deprecated -DMACOS_BUILD - CXXFLAGS_DEBUG += -Wno-deprecated -DMACOS_BUILD - LDFLAGS += -framework OpenGL + CXXFLAGS += -DMACOS_BUILD + CXXFLAGS_DEBUG += -DMACOS_BUILD # Configurar arquitectura (por defecto arm64, como en CMake) CXXFLAGS += -arch arm64 CXXFLAGS_DEBUG += -arch arm64 @@ -254,7 +252,7 @@ macos_release: # Compila la versión para procesadores Intel ifdef ENABLE_MACOS_X86_64 - $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -framework OpenGL -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15 + $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15 # Firma la aplicación codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app" @@ -278,7 +276,7 @@ ifdef ENABLE_MACOS_X86_64 endif # Compila la versión para procesadores Apple Silicon - $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -DSDL_DISABLE_IMMINTRIN_H -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -framework OpenGL -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11 + $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -DSDL_DISABLE_IMMINTRIN_H -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11 # Firma la aplicación codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app" @@ -518,6 +516,10 @@ help: @echo " show_version - Mostrar version actual ($(VERSION))" @echo " help - Mostrar esta ayuda" -.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool resources.pack +spirv: + @echo "Compilando shaders SPIR-V..." + tools/shaders/compile_spirv.sh + +.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool resources.pack spirv FORCE: \ No newline at end of file diff --git a/config/assets.txt b/config/assets.txt index b8f08d6..9e2025a 100644 --- a/config/assets.txt +++ b/config/assets.txt @@ -6,6 +6,7 @@ # Archivos de configuración del sistema (absolutos y opcionales) DATA|${SYSTEM_FOLDER}/config.yaml|optional,absolute DATA|${SYSTEM_FOLDER}/controllers.json|optional,absolute +DATA|${SYSTEM_FOLDER}/postfx.yaml|optional,absolute DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute # Archivos de configuración del juego diff --git a/data/shaders/postfx.frag b/data/shaders/postfx.frag new file mode 100644 index 0000000..9a66a9f --- /dev/null +++ b/data/shaders/postfx.frag @@ -0,0 +1,144 @@ +#version 450 + +// Vulkan GLSL fragment shader — PostFX effects +// Used for SDL3 GPU API (SPIR-V path, Win/Linux). +// Compile: glslc postfx.frag -o postfx.frag.spv +// xxd -i postfx.frag.spv > ../../source/core/rendering/sdl3gpu/postfx_frag_spv.h +// +// PostFXUniforms must match exactly the C++ struct in sdl3gpu_shader.hpp +// (8 floats, 32 bytes, std140/scalar layout). + +layout(location = 0) in vec2 v_uv; +layout(location = 0) out vec4 out_color; + +layout(set = 2, binding = 0) uniform sampler2D scene; + +layout(set = 3, binding = 0) uniform PostFXUniforms { + float vignette_strength; + float chroma_strength; + float scanline_strength; + float screen_height; + float mask_strength; + float gamma_strength; + float curvature; + float bleeding; + float pixel_scale; // physical pixels per logical pixel (vh / tex_height_) + float time; // seconds since SDL init + float oversample; // supersampling factor (1.0 = off, 3.0 = 3×SS) + float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — 48 bytes total (3 × 16) +} u; + +// YCbCr helpers for NTSC bleeding +vec3 rgb_to_ycc(vec3 rgb) { + return vec3( + 0.299*rgb.r + 0.587*rgb.g + 0.114*rgb.b, + -0.169*rgb.r - 0.331*rgb.g + 0.500*rgb.b + 0.5, + 0.500*rgb.r - 0.419*rgb.g - 0.081*rgb.b + 0.5 + ); +} +vec3 ycc_to_rgb(vec3 ycc) { + float y = ycc.x; + float cb = ycc.y - 0.5; + float cr = ycc.z - 0.5; + return clamp(vec3( + y + 1.402*cr, + y - 0.344*cb - 0.714*cr, + y + 1.772*cb + ), 0.0, 1.0); +} + +void main() { + vec2 uv = v_uv; + + // Curvatura barrel CRT + if (u.curvature > 0.0) { + vec2 c = uv - 0.5; + float rsq = dot(c, c); + vec2 dist = vec2(0.05, 0.1) * u.curvature; + vec2 barrelScale = vec2(1.0) - 0.23 * dist; + c += c * (dist * rsq); + c *= barrelScale; + if (abs(c.x) >= 0.5 || abs(c.y) >= 0.5) { + out_color = vec4(0.0, 0.0, 0.0, 1.0); + return; + } + uv = c + 0.5; + } + + // Muestra base + vec3 base = texture(scene, uv).rgb; + + // Sangrado NTSC — difuminado horizontal de crominancia. + // step = 1 pixel lógico de juego en UV (corrige SS: textureSize.x = game_w * oversample). + vec3 colour; + if (u.bleeding > 0.0) { + float tw = float(textureSize(scene, 0).x); + float step = u.oversample / tw; // 1 pixel lógico en UV + vec3 ycc = rgb_to_ycc(base); + vec3 ycc_l2 = rgb_to_ycc(texture(scene, uv - vec2(2.0*step, 0.0)).rgb); + vec3 ycc_l1 = rgb_to_ycc(texture(scene, uv - vec2(1.0*step, 0.0)).rgb); + vec3 ycc_r1 = rgb_to_ycc(texture(scene, uv + vec2(1.0*step, 0.0)).rgb); + vec3 ycc_r2 = rgb_to_ycc(texture(scene, uv + vec2(2.0*step, 0.0)).rgb); + ycc.yz = (ycc_l2.yz + ycc_l1.yz*2.0 + ycc.yz*2.0 + ycc_r1.yz*2.0 + ycc_r2.yz) / 8.0; + colour = mix(base, ycc_to_rgb(ycc), u.bleeding); + } else { + colour = base; + } + + // Aberración cromática (drift animado con time para efecto NTSC real) + float ca = u.chroma_strength * 0.005 * (1.0 + 0.15 * sin(u.time * 7.3)); + colour.r = texture(scene, uv + vec2(ca, 0.0)).r; + colour.b = texture(scene, uv - vec2(ca, 0.0)).b; + + // Corrección gamma (linealizar antes de scanlines, codificar después) + if (u.gamma_strength > 0.0) { + vec3 lin = pow(colour, vec3(2.4)); + colour = mix(colour, lin, u.gamma_strength); + } + + // Scanlines — 1 pixel físico oscuro por fila lógica. + // Usa uv.y (independiente del offset de letterbox) con pixel_scale para + // calcular la posición dentro de la fila en coordenadas físicas. + // 3x: 1 dark + 2 bright. 4x: 1 dark + 3 bright. + // bright=3.5×, dark floor=0.42 (mantiene aspecto CRT original). + if (u.scanline_strength > 0.0) { + float ps = max(1.0, round(u.pixel_scale)); + float frac_in_row = fract(uv.y * u.screen_height); + float row_pos = floor(frac_in_row * ps); + float is_dark = step(ps - 1.0, row_pos); + float scan = mix(3.5, 0.42, is_dark); + colour *= mix(1.0, scan, u.scanline_strength); + } + + if (u.gamma_strength > 0.0) { + vec3 enc = pow(colour, vec3(1.0 / 2.2)); + colour = mix(colour, enc, u.gamma_strength); + } + + // Viñeta + vec2 d = uv - 0.5; + float vignette = 1.0 - dot(d, d) * u.vignette_strength; + colour *= clamp(vignette, 0.0, 1.0); + + // Máscara de fósforo RGB — después de scanlines (orden original): + // filas brillantes saturadas → máscara invisible, filas oscuras → RGB visible. + if (u.mask_strength > 0.0) { + float whichMask = fract(gl_FragCoord.x * 0.3333333); + vec3 mask = vec3(0.80); + if (whichMask < 0.3333333) + mask.x = 1.0; + else if (whichMask < 0.6666666) + mask.y = 1.0; + else + mask.z = 1.0; + colour = mix(colour, colour * mask, u.mask_strength); + } + + // Parpadeo de fósforo CRT (~50 Hz) + if (u.flicker > 0.0) { + float flicker_wave = sin(u.time * 100.0) * 0.5 + 0.5; + colour *= 1.0 - u.flicker * 0.04 * flicker_wave; + } + + out_color = vec4(colour, 1.0); +} diff --git a/data/shaders/postfx.vert b/data/shaders/postfx.vert new file mode 100644 index 0000000..eab75cf --- /dev/null +++ b/data/shaders/postfx.vert @@ -0,0 +1,24 @@ +#version 450 + +// Vulkan GLSL vertex shader — postfx full-screen triangle +// Used for SDL3 GPU API (SPIR-V path, Win/Linux). +// Compile: glslc postfx.vert -o postfx.vert.spv +// xxd -i postfx.vert.spv > ../../source/core/rendering/sdl3gpu/postfx_vert_spv.h + +layout(location = 0) out vec2 v_uv; + +void main() { + // Full-screen triangle (no vertex buffer needed) + const vec2 positions[3] = vec2[3]( + vec2(-1.0, -1.0), + vec2( 3.0, -1.0), + vec2(-1.0, 3.0) + ); + const vec2 uvs[3] = vec2[3]( + vec2(0.0, 1.0), + vec2(2.0, 1.0), + vec2(0.0,-1.0) + ); + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + v_uv = uvs[gl_VertexIndex]; +} diff --git a/source/defaults.hpp b/source/defaults.hpp index 37af09c..47a4cf2 100644 --- a/source/defaults.hpp +++ b/source/defaults.hpp @@ -221,6 +221,8 @@ namespace GameDefaults { constexpr bool VIDEO_VSYNC = true; constexpr bool VIDEO_INTEGER_SCALE = true; constexpr bool VIDEO_SHADERS = false; + constexpr bool VIDEO_POSTFX = false; + constexpr bool VIDEO_SUPERSAMPLING = false; // Music constexpr bool MUSIC_ENABLED = true; diff --git a/source/director.cpp b/source/director.cpp index f427ca6..280f477 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -105,7 +105,9 @@ void Director::init() { Logger::section("INIT CONFIG"); Options::setConfigFile(Asset::get()->getPath("config.yaml")); // Establece el fichero de configuración Options::setControllersFile(Asset::get()->getPath("controllers.json")); // Establece el fichero de configuración de mandos - Options::loadFromFile(); // Carga el archivo de configuración + Options::setPostFXFile(Asset::get()->getPath("postfx.yaml")); // Establece el fichero de presets PostFX + Options::loadFromFile(); // Carga el archivo de configuración + Options::loadPostFXFromFile(); // Carga los presets PostFX loadParams(); // Carga los parámetros del programa loadScoreFile(); // Carga el archivo de puntuaciones diff --git a/source/global_inputs.cpp b/source/global_inputs.cpp index 09d2bd0..ab0f310 100644 --- a/source/global_inputs.cpp +++ b/source/global_inputs.cpp @@ -62,10 +62,23 @@ namespace GlobalInputs { Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.vsync)}); } - // Activa o desactiva los shaders - void toggleShaders() { - Screen::toggleShaders(); - Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)}); + // Activa o desactiva los efectos PostFX + void togglePostFX() { + Screen::togglePostFX(); + Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.postfx)}); + } + + // Avanza al siguiente preset PostFX + void nextPostFXPreset() { + Screen::nextPostFXPreset(); + const std::string name = Options::postfx_presets.empty() ? "" : Options::postfx_presets.at(static_cast(Options::current_postfx_preset)).name; + Notifier::get()->show({"PostFX: " + name}); + } + + // Activa o desactiva el supersampling 3x + void toggleSupersampling() { + Screen::toggleSupersampling(); + Notifier::get()->show({"3x SS: " + boolToOnOff(Options::video.supersampling)}); } // Cambia al siguiente idioma @@ -169,7 +182,6 @@ namespace GlobalInputs { {Action::TOGGLE_AUDIO, toggleAudio}, {Action::TOGGLE_AUTO_FIRE, toggleFireMode}, {Action::CHANGE_LANG, setNextLang}, - {Action::TOGGLE_VIDEO_SHADERS, toggleShaders}, {Action::TOGGLE_VIDEO_INTEGER_SCALE, toggleIntegerScale}, {Action::TOGGLE_VIDEO_VSYNC, toggleVSync}, #ifdef _DEBUG @@ -177,13 +189,29 @@ namespace GlobalInputs { #endif }; - return std::ranges::any_of(ACTIONS, [](const auto& pair) -> auto { - if (Input::get()->checkAction(pair.first, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { - pair.second(); - return true; + if (std::ranges::any_of(ACTIONS, [](const auto& pair) -> auto { + if (Input::get()->checkAction(pair.first, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { + pair.second(); + return true; + } + return false; + })) { + return true; + } + + // F4 con modificadores: Ctrl+F4 = supersampling, Shift+F4 = siguiente preset, F4 = toggle PostFX + if (Input::get()->checkAction(Input::Action::TOGGLE_VIDEO_POSTFX, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { + if ((SDL_GetModState() & SDL_KMOD_CTRL) != 0U) { + toggleSupersampling(); + } else if (Options::video.postfx && ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0U)) { + nextPostFXPreset(); + } else { + togglePostFX(); } - return false; - }); + return true; + } + + return false; } // Comprueba el resto de entradas diff --git a/source/input.hpp b/source/input.hpp index 7bca65b..fac9dfa 100644 --- a/source/input.hpp +++ b/source/input.hpp @@ -82,6 +82,7 @@ class Input { {Action::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)}, {Action::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)}, {Action::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)}, + {Action::TOGGLE_VIDEO_POSTFX, KeyState(SDL_SCANCODE_F4)}, {Action::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)}, {Action::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)}, diff --git a/source/input_types.cpp b/source/input_types.cpp index 493adfa..8ac1832 100644 --- a/source/input_types.cpp +++ b/source/input_types.cpp @@ -22,6 +22,7 @@ const std::unordered_map ACTION_TO_STRING = { {InputAction::WINDOW_INC_SIZE, "WINDOW_INC_SIZE"}, {InputAction::WINDOW_DEC_SIZE, "WINDOW_DEC_SIZE"}, {InputAction::TOGGLE_VIDEO_SHADERS, "TOGGLE_VIDEO_SHADERS"}, + {InputAction::TOGGLE_VIDEO_POSTFX, "TOGGLE_VIDEO_POSTFX"}, {InputAction::TOGGLE_VIDEO_INTEGER_SCALE, "TOGGLE_VIDEO_INTEGER_SCALE"}, {InputAction::TOGGLE_VIDEO_VSYNC, "TOGGLE_VIDEO_VSYNC"}, {InputAction::RESET, "RESET"}, @@ -52,6 +53,7 @@ const std::unordered_map STRING_TO_ACTION = { {"WINDOW_INC_SIZE", InputAction::WINDOW_INC_SIZE}, {"WINDOW_DEC_SIZE", InputAction::WINDOW_DEC_SIZE}, {"TOGGLE_VIDEO_SHADERS", InputAction::TOGGLE_VIDEO_SHADERS}, + {"TOGGLE_VIDEO_POSTFX", InputAction::TOGGLE_VIDEO_POSTFX}, {"TOGGLE_VIDEO_INTEGER_SCALE", InputAction::TOGGLE_VIDEO_INTEGER_SCALE}, {"TOGGLE_VIDEO_VSYNC", InputAction::TOGGLE_VIDEO_VSYNC}, {"RESET", InputAction::RESET}, diff --git a/source/input_types.hpp b/source/input_types.hpp index 3fa497b..d310f66 100644 --- a/source/input_types.hpp +++ b/source/input_types.hpp @@ -31,7 +31,8 @@ enum class InputAction : int { // Acciones de entrada posibles en el juego WINDOW_FULLSCREEN, WINDOW_INC_SIZE, WINDOW_DEC_SIZE, - TOGGLE_VIDEO_SHADERS, + TOGGLE_VIDEO_SHADERS, // backward compat alias + TOGGLE_VIDEO_POSTFX, TOGGLE_VIDEO_INTEGER_SCALE, TOGGLE_VIDEO_VSYNC, RESET, diff --git a/source/options.cpp b/source/options.cpp index 983d48f..a946efc 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -24,6 +24,16 @@ namespace Options { GamepadManager gamepad_manager; // Opciones de mando para cada jugador Keyboard keyboard; // Opciones para el teclado PendingChanges pending_changes; // Opciones que se aplican al cerrar + std::vector postfx_presets = { // Lista de presets de PostFX + {"CRT", 0.6F, 0.7F, 0.15F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F}, + {"NTSC", 0.4F, 0.5F, 0.2F, 0.3F, 0.3F, 0.0F, 0.6F, 0.0F}, + {"CURVED", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}, + {"SCANLINES", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, + {"SUBTLE", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}, + {"CRT LIVE", 0.5F, 0.6F, 0.3F, 0.3F, 0.4F, 0.3F, 0.4F, 0.8F}, + }; + int current_postfx_preset = 0; // Índice del preset PostFX activo + std::string postfx_file_path; // Ruta al fichero de presets PostFX // Establece el fichero de configuración void setConfigFile(const std::string& file_path) { settings.config_file = file_path; } @@ -31,6 +41,166 @@ namespace Options { // Establece el fichero de configuración de mandos void setControllersFile(const std::string& file_path) { settings.controllers_file = file_path; } + // Establece la ruta del fichero de PostFX + void setPostFXFile(const std::string& path) { postfx_file_path = path; } + + // Helper: extrae un campo float de un nodo YAML si existe, ignorando errores de conversión + static void parseFloatField(const fkyaml::node& node, const std::string& key, float& target) { + if (node.contains(key)) { + try { + target = node[key].get_value(); + } catch (...) {} + } + } + + // Carga los presets de PostFX desde el fichero + auto loadPostFXFromFile() -> bool { + postfx_presets.clear(); + + std::ifstream file(postfx_file_path); + if (!file.good()) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "PostFX file not found, creating default: %s", postfx_file_path.c_str()); + return savePostFXToFile(); + } + + std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + + try { + auto yaml = fkyaml::node::deserialize(content); + + if (yaml.contains("presets")) { + const auto& presets = yaml["presets"]; + for (const auto& p : presets) { + PostFXPreset preset; + if (p.contains("name")) { + preset.name = p["name"].get_value(); + } + parseFloatField(p, "vignette", preset.vignette); + parseFloatField(p, "scanlines", preset.scanlines); + parseFloatField(p, "chroma", preset.chroma); + parseFloatField(p, "mask", preset.mask); + parseFloatField(p, "gamma", preset.gamma); + parseFloatField(p, "curvature", preset.curvature); + parseFloatField(p, "bleeding", preset.bleeding); + parseFloatField(p, "flicker", preset.flicker); + postfx_presets.push_back(preset); + } + } + + if (!postfx_presets.empty()) { + current_postfx_preset = std::clamp( + current_postfx_preset, 0, + static_cast(postfx_presets.size()) - 1); + } else { + current_postfx_preset = 0; + } + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "PostFX file loaded: %zu preset(s)", postfx_presets.size()); + return true; + + } catch (const fkyaml::exception& e) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Error parsing PostFX YAML: %s. Recreating defaults.", e.what()); + return savePostFXToFile(); + } + } + + // Guarda los presets de PostFX por defecto al fichero + auto savePostFXToFile() -> bool { + if (postfx_file_path.empty()) { + return false; + } + + std::ofstream file(postfx_file_path); + if (!file.is_open()) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: %s can't be opened for writing", postfx_file_path.c_str()); + return false; + } + + file << "# Coffee Crisis Arcade Edition - PostFX Presets\n"; + file << "# Each preset defines the intensity of post-processing effects (0.0 to 1.0).\n"; + file << "# vignette: screen darkening at the edges\n"; + file << "# scanlines: horizontal scanline effect\n"; + file << "# chroma: chromatic aberration (RGB color fringing)\n"; + file << "# mask: phosphor dot mask (RGB subpixel pattern)\n"; + file << "# gamma: gamma correction input 2.4 / output 2.2\n"; + file << "# curvature: CRT barrel distortion\n"; + file << "# bleeding: NTSC horizontal colour bleeding\n"; + file << "# flicker: phosphor CRT flicker ~50 Hz (0.0 = off, 1.0 = max)\n"; + file << "\n"; + file << "presets:\n"; + file << " - name: \"CRT\"\n"; + file << " vignette: 0.6\n"; + file << " scanlines: 0.7\n"; + file << " chroma: 0.15\n"; + file << " mask: 0.5\n"; + file << " gamma: 0.5\n"; + file << " curvature: 0.0\n"; + file << " bleeding: 0.0\n"; + file << " flicker: 0.0\n"; + file << " - name: \"NTSC\"\n"; + file << " vignette: 0.4\n"; + file << " scanlines: 0.5\n"; + file << " chroma: 0.2\n"; + file << " mask: 0.3\n"; + file << " gamma: 0.3\n"; + file << " curvature: 0.0\n"; + file << " bleeding: 0.6\n"; + file << " flicker: 0.0\n"; + file << " - name: \"CURVED\"\n"; + file << " vignette: 0.5\n"; + file << " scanlines: 0.6\n"; + file << " chroma: 0.1\n"; + file << " mask: 0.4\n"; + file << " gamma: 0.4\n"; + file << " curvature: 0.8\n"; + file << " bleeding: 0.0\n"; + file << " flicker: 0.0\n"; + file << " - name: \"SCANLINES\"\n"; + file << " vignette: 0.0\n"; + file << " scanlines: 0.8\n"; + file << " chroma: 0.0\n"; + file << " mask: 0.0\n"; + file << " gamma: 0.0\n"; + file << " curvature: 0.0\n"; + file << " bleeding: 0.0\n"; + file << " flicker: 0.0\n"; + file << " - name: \"SUBTLE\"\n"; + file << " vignette: 0.3\n"; + file << " scanlines: 0.4\n"; + file << " chroma: 0.05\n"; + file << " mask: 0.0\n"; + file << " gamma: 0.2\n"; + file << " curvature: 0.0\n"; + file << " bleeding: 0.0\n"; + file << " flicker: 0.0\n"; + file << " - name: \"CRT LIVE\"\n"; + file << " vignette: 0.5\n"; + file << " scanlines: 0.6\n"; + file << " chroma: 0.3\n"; + file << " mask: 0.3\n"; + file << " gamma: 0.4\n"; + file << " curvature: 0.3\n"; + file << " bleeding: 0.4\n"; + file << " flicker: 0.8\n"; + + file.close(); + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "PostFX file created with defaults: %s", postfx_file_path.c_str()); + + // Cargar los presets recién escritos + postfx_presets.clear(); + postfx_presets.push_back({"CRT", 0.6F, 0.7F, 0.15F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"NTSC", 0.4F, 0.5F, 0.2F, 0.3F, 0.3F, 0.0F, 0.6F, 0.0F}); + postfx_presets.push_back({"CURVED", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}); + postfx_presets.push_back({"SCANLINES", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"SUBTLE", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"CRT LIVE", 0.5F, 0.6F, 0.3F, 0.3F, 0.4F, 0.3F, 0.4F, 0.8F}); + current_postfx_preset = 0; + + return true; + } + // Inicializa las opciones del programa void init() { // Dificultades @@ -78,6 +248,20 @@ namespace Options { if (vid.contains("shaders")) { try { video.shaders = vid["shaders"].get_value(); } catch (...) {} } + if (vid.contains("postfx")) { + try { video.postfx = vid["postfx"].get_value(); } catch (...) {} + } + if (vid.contains("supersampling")) { + try { video.supersampling = vid["supersampling"].get_value(); } catch (...) {} + } + if (vid.contains("postfx_preset")) { + try { + int preset = vid["postfx_preset"].get_value(); + if (preset >= 0 && preset < static_cast(postfx_presets.size())) { + current_postfx_preset = preset; + } + } catch (...) {} + } } void loadAudioFromYaml(const fkyaml::node& yaml) { @@ -247,6 +431,9 @@ namespace Options { file << " vsync: " << boolToString(video.vsync) << "\n"; file << " integer_scale: " << boolToString(video.integer_scale) << "\n"; file << " shaders: " << boolToString(video.shaders) << "\n"; + file << " postfx: " << boolToString(video.postfx) << "\n"; + file << " supersampling: " << boolToString(video.supersampling) << "\n"; + file << " postfx_preset: " << current_postfx_preset << "\n"; file << "\n"; // AUDIO diff --git a/source/options.hpp b/source/options.hpp index a3985a5..08b7369 100644 --- a/source/options.hpp +++ b/source/options.hpp @@ -24,6 +24,18 @@ namespace Options { // --- Estructuras --- + struct PostFXPreset { + std::string name; + float vignette{0.6F}; + float scanlines{0.7F}; + float chroma{0.15F}; + float mask{0.0F}; + float gamma{0.0F}; + float curvature{0.0F}; + float bleeding{0.0F}; + float flicker{0.0F}; + }; + struct Window { std::string caption = GameDefaults::Options::WINDOW_CAPTION; // Texto que aparece en la barra de título de la ventana int zoom = GameDefaults::Options::WINDOW_ZOOM; // Valor por el que se multiplica el tamaño de la ventana @@ -35,7 +47,9 @@ namespace Options { bool fullscreen = GameDefaults::Options::VIDEO_FULLSCREEN; // Indica si se usa pantalla completa bool vsync = GameDefaults::Options::VIDEO_VSYNC; // Indica si se usa vsync bool integer_scale = GameDefaults::Options::VIDEO_INTEGER_SCALE; // Indica si se usa escalado entero - bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo + bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo (backward compat) + bool postfx = GameDefaults::Options::VIDEO_POSTFX; // Indica si se usan efectos PostFX + bool supersampling = GameDefaults::Options::VIDEO_SUPERSAMPLING; // Indica si se usa supersampling 3x std::string info; // Información sobre el modo de vídeo }; @@ -278,11 +292,17 @@ namespace Options { extern GamepadManager gamepad_manager; // Manager de mandos para cada jugador extern Keyboard keyboard; // Opciones para el teclado extern PendingChanges pending_changes; // Opciones que se aplican al cerrar + extern std::vector postfx_presets; // Lista de presets de PostFX + extern int current_postfx_preset; // Índice del preset PostFX activo + extern std::string postfx_file_path; // Ruta al fichero de presets PostFX // --- Funciones --- void init(); // Inicializa las opciones del programa void setConfigFile(const std::string& file_path); // Establece el fichero de configuración void setControllersFile(const std::string& file_path); // Establece el fichero de configuración de mandos + void setPostFXFile(const std::string& path); // Establece el fichero de presets PostFX + auto loadPostFXFromFile() -> bool; // Carga los presets PostFX desde fichero + auto savePostFXToFile() -> bool; // Guarda los presets PostFX por defecto al fichero auto loadFromFile() -> bool; // Carga el fichero de configuración auto saveToFile() -> bool; // Guarda el fichero de configuración void setKeyboardToPlayer(Player::Id player_id); // Asigna el teclado al jugador diff --git a/source/rendering/opengl/opengl_shader.cpp b/source/rendering/opengl/opengl_shader.cpp deleted file mode 100644 index 9c58c51..0000000 --- a/source/rendering/opengl/opengl_shader.cpp +++ /dev/null @@ -1,522 +0,0 @@ -#include "opengl_shader.hpp" - -#include - -#include -#include -#include -#include - -#include "ui/logger.hpp" // Para Loger - -namespace Rendering { - - OpenGLShader::~OpenGLShader() { - cleanup(); - } - -#ifndef __APPLE__ - auto OpenGLShader::initGLExtensions() -> bool { - glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"); - glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"); - glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"); - glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"); - glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"); - glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"); - glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"); - glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"); - glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"); - glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram"); - glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"); - glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog"); - glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"); - glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram"); - glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation"); - glUniform2f = (PFNGLUNIFORM2FPROC)SDL_GL_GetProcAddress("glUniform2f"); - glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glGenVertexArrays"); - glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)SDL_GL_GetProcAddress("glBindVertexArray"); - glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glDeleteVertexArrays"); - glGenBuffers = (PFNGLGENBUFFERSPROC)SDL_GL_GetProcAddress("glGenBuffers"); - glBindBuffer = (PFNGLBINDBUFFERPROC)SDL_GL_GetProcAddress("glBindBuffer"); - glBufferData = (PFNGLBUFFERDATAPROC)SDL_GL_GetProcAddress("glBufferData"); - glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)SDL_GL_GetProcAddress("glDeleteBuffers"); - glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"); - glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"); - - return (glCreateShader != nullptr) && (glShaderSource != nullptr) && (glCompileShader != nullptr) && (glGetShaderiv != nullptr) && - (glGetShaderInfoLog != nullptr) && (glDeleteShader != nullptr) && (glAttachShader != nullptr) && (glCreateProgram != nullptr) && - (glLinkProgram != nullptr) && (glValidateProgram != nullptr) && (glGetProgramiv != nullptr) && (glGetProgramInfoLog != nullptr) && - (glUseProgram != nullptr) && (glDeleteProgram != nullptr) && (glGetUniformLocation != nullptr) && (glUniform2f != nullptr) && - (glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) && - (glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) && - (glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr); - } -#endif - - void OpenGLShader::checkGLError(const char* operation) { - GLenum error = glGetError(); - if (error != GL_NO_ERROR) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error OpenGL en %s: 0x%x", - operation, - error); - } - } - - auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint { - if (source.empty()) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "ERROR: El código fuente del shader está vacío"); - return 0; - } - - GLuint shader_id = glCreateShader(shader_type); - if (shader_id == 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear shader"); - checkGLError("glCreateShader"); - return 0; - } - - std::array sources = {source.c_str()}; - glShaderSource(shader_id, 1, sources.data(), nullptr); - checkGLError("glShaderSource"); - - glCompileShader(shader_id); - checkGLError("glCompileShader"); - - // Verificar compilación - GLint compiled = GL_FALSE; - glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled); - if (compiled != GL_TRUE) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error en compilación del shader"); - GLint log_length; - glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length); - if (log_length > 0) { - std::vector log(log_length); - glGetShaderInfoLog(shader_id, log_length, &log_length, log.data()); - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Log de compilación: %s", - log.data()); - } - glDeleteShader(shader_id); - return 0; - } - - return shader_id; - } - - auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint { - GLuint program = glCreateProgram(); - if (program == 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error al crear programa de shaders"); - return 0; - } - - glAttachShader(program, vertex_shader); - checkGLError("glAttachShader(vertex)"); - glAttachShader(program, fragment_shader); - checkGLError("glAttachShader(fragment)"); - - glLinkProgram(program); - checkGLError("glLinkProgram"); - - // Verificar enlace - GLint linked = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (linked != GL_TRUE) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error al enlazar programa"); - GLint log_length; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); - if (log_length > 0) { - std::vector log(log_length); - glGetProgramInfoLog(program, log_length, &log_length, log.data()); - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Log de enlace: %s", - log.data()); - } - glDeleteProgram(program); - return 0; - } - - glValidateProgram(program); - checkGLError("glValidateProgram"); - - return program; - } - - void OpenGLShader::createQuadGeometry() { - // Datos del quad: posición (x, y) + coordenadas de textura (u, v) - // Formato: x, y, u, v - std::array vertices = { - // Posición // TexCoords - -1.0F, - -1.0F, - 0.0F, - 0.0F, // Inferior izquierda - 1.0F, - -1.0F, - 1.0F, - 0.0F, // Inferior derecha - 1.0F, - 1.0F, - 1.0F, - 1.0F, // Superior derecha - -1.0F, - 1.0F, - 0.0F, - 1.0F // Superior izquierda - }; - - // Índices para dibujar el quad con dos triángulos - std::array indices = { - 0, - 1, - 2, // Primer triángulo - 2, - 3, - 0 // Segundo triángulo - }; - - // Generar y configurar VAO - glGenVertexArrays(1, &vao_); - glBindVertexArray(vao_); - checkGLError("glBindVertexArray"); - - // Generar y configurar VBO - glGenBuffers(1, &vbo_); - glBindBuffer(GL_ARRAY_BUFFER, vbo_); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW); - checkGLError("glBufferData(VBO)"); - - // Generar y configurar EBO - glGenBuffers(1, &ebo_); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW); - checkGLError("glBufferData(EBO)"); - - // Atributo 0: Posición (2 floats) - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), nullptr); - glEnableVertexAttribArray(0); - checkGLError("glVertexAttribPointer(position)"); - - // Atributo 1: Coordenadas de textura (2 floats) - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), static_cast(static_cast(nullptr) + (2 * sizeof(float)))); - glEnableVertexAttribArray(1); - checkGLError("glVertexAttribPointer(texcoord)"); - - // Desvincular - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - - auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint { - if (texture == nullptr) { - return 1; - } - - SDL_PropertiesID props = SDL_GetTextureProperties(texture); - GLuint texture_id = 0; - - // Intentar obtener ID de textura OpenGL - texture_id = static_cast(reinterpret_cast(SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr))); - - if (texture_id == 0) { - texture_id = static_cast(reinterpret_cast(SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr))); - } - - if (texture_id == 0) { - texture_id = static_cast(SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", 1)); - } - - if (texture_id == 0) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No se pudo obtener ID de textura OpenGL, usando 1 por defecto"); - texture_id = 1; - } - - return texture_id; - } - - auto OpenGLShader::init(SDL_Window* window, - SDL_Texture* texture, - const std::string& vertex_source, - const std::string& fragment_source) -> bool { - window_ = window; - back_buffer_ = texture; - renderer_ = SDL_GetRenderer(window); - - if (renderer_ == nullptr) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error: No se pudo obtener el renderer"); - return false; - } - - // Obtener tamaños - SDL_GetWindowSize(window_, &window_width_, &window_height_); - SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_); - - /* - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f", - window_width_, - window_height_, - texture_width_, - texture_height_); - */ - - Logger::info( - "Inicializando shaders: ventana=" + - std::to_string(window_width_) + - "x" + - std::to_string(window_height_) + - ", textura=" + - std::to_string(static_cast(texture_width_)) + - "x" + - std::to_string(static_cast(texture_height_))); - - // Verificar que es OpenGL - const char* renderer_name = SDL_GetRendererName(renderer_); - if ((renderer_name == nullptr) || strncmp(renderer_name, "opengl", 6) != 0) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Renderer no es OpenGL: %s", - (renderer_name != nullptr) ? renderer_name : "unknown"); - return false; - } - -#ifndef __APPLE__ - // Inicializar extensiones OpenGL en Windows/Linux - if (!initGLExtensions()) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error al inicializar extensiones OpenGL"); - return false; - } -#endif - - // Limpiar shader anterior si existe - if (program_id_ != 0) { - glDeleteProgram(program_id_); - program_id_ = 0; - } - - // Compilar shaders - GLuint vertex_shader = compileShader(vertex_source, GL_VERTEX_SHADER); - GLuint fragment_shader = compileShader(fragment_source, GL_FRAGMENT_SHADER); - - if (vertex_shader == 0 || fragment_shader == 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error al compilar shaders"); - if (vertex_shader != 0) { - glDeleteShader(vertex_shader); - } - if (fragment_shader != 0) { - glDeleteShader(fragment_shader); - } - return false; - } - - // Enlazar programa - program_id_ = linkProgram(vertex_shader, fragment_shader); - - // Limpiar shaders (ya no necesarios tras el enlace) - glDeleteShader(vertex_shader); - glDeleteShader(fragment_shader); - - if (program_id_ == 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Error al crear programa de shaders"); - return false; - } - - // Crear geometría del quad - createQuadGeometry(); - - // Obtener ubicación del uniform TextureSize - glUseProgram(program_id_); - texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize"); - if (texture_size_location_ != -1) { - /* - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Configurando TextureSize uniform: %.0fx%.0f", - texture_width_, - texture_height_); - */ - Logger::info( - "Configurando TextureSize uniform: " + - std::to_string(static_cast(texture_width_)) + - "x" + - std::to_string(static_cast(texture_height_))); - glUniform2f(texture_size_location_, texture_width_, texture_height_); - checkGLError("glUniform2f(TextureSize)"); - } else { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Uniform 'TextureSize' no encontrado en shader"); - } - glUseProgram(0); - - is_initialized_ = true; - /* - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "** OpenGL 3.3 Shader Backend inicializado correctamente"); - */ - Logger::info("OpenGL 3.3 Shader Backend inicializado correctamente"); - return true; - } - - void OpenGLShader::render() { - if (!is_initialized_ || program_id_ == 0) { - // Fallback: renderizado SDL normal - SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); - SDL_SetRenderTarget(renderer_, nullptr); - SDL_RenderClear(renderer_); - SDL_RenderTexture(renderer_, back_buffer_, nullptr, nullptr); - SDL_RenderPresent(renderer_); - return; - } - - // Obtener tamaño actual de ventana (puede haber cambiado) - int current_width; - int current_height; - SDL_GetWindowSize(window_, ¤t_width, ¤t_height); - - // Guardar estados OpenGL - GLint old_program; - glGetIntegerv(GL_CURRENT_PROGRAM, &old_program); - - std::array old_viewport{}; - glGetIntegerv(GL_VIEWPORT, old_viewport.data()); - - GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D); - GLint old_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture); - - GLint old_vao; - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao); - - // Preparar renderizado - SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); - SDL_SetRenderTarget(renderer_, nullptr); - SDL_RenderClear(renderer_); - - // Obtener y bindear textura - GLuint texture_id = getTextureID(back_buffer_); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture_id); - checkGLError("glBindTexture"); - - // Usar nuestro programa - glUseProgram(program_id_); - checkGLError("glUseProgram"); - - // Configurar viewport (obtener tamaño lógico de SDL) - int logical_w; - int logical_h; - SDL_RendererLogicalPresentation mode; - SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode); - - if (logical_w == 0 || logical_h == 0) { - logical_w = current_width; - logical_h = current_height; - } - - // Calcular viewport considerando aspect ratio - int viewport_x = 0; - int viewport_y = 0; - int viewport_w = current_width; - int viewport_h = current_height; - - if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) { - int scale_x = current_width / logical_w; - int scale_y = current_height / logical_h; - int scale = (scale_x < scale_y) ? scale_x : scale_y; - scale = std::max(scale, 1); - - viewport_w = logical_w * scale; - viewport_h = logical_h * scale; - viewport_x = (current_width - viewport_w) / 2; - viewport_y = (current_height - viewport_h) / 2; - } else { - float window_aspect = static_cast(current_width) / current_height; - float logical_aspect = static_cast(logical_w) / logical_h; - - if (window_aspect > logical_aspect) { - viewport_w = static_cast(logical_aspect * current_height); - viewport_x = (current_width - viewport_w) / 2; - } else { - viewport_h = static_cast(current_width / logical_aspect); - viewport_y = (current_height - viewport_h) / 2; - } - } - - glViewport(viewport_x, viewport_y, viewport_w, viewport_h); - checkGLError("glViewport"); - - // Dibujar quad usando VAO - glBindVertexArray(vao_); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); - checkGLError("glDrawElements"); - - // Presentar - SDL_GL_SwapWindow(window_); - - // Restaurar estados OpenGL - glUseProgram(old_program); - glBindTexture(GL_TEXTURE_2D, old_texture); - if (was_texture_enabled == 0U) { - glDisable(GL_TEXTURE_2D); - } - glBindVertexArray(old_vao); - glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); - } - - void OpenGLShader::setTextureSize(float width, float height) { - if (!is_initialized_ || program_id_ == 0) { - return; - } - - texture_width_ = width; - texture_height_ = height; - - GLint old_program; - glGetIntegerv(GL_CURRENT_PROGRAM, &old_program); - - glUseProgram(program_id_); - - if (texture_size_location_ != -1) { - glUniform2f(texture_size_location_, width, height); - checkGLError("glUniform2f(TextureSize)"); - } - - glUseProgram(old_program); - } - - void OpenGLShader::cleanup() { - if (vao_ != 0) { - glDeleteVertexArrays(1, &vao_); - vao_ = 0; - } - - if (vbo_ != 0) { - glDeleteBuffers(1, &vbo_); - vbo_ = 0; - } - - if (ebo_ != 0) { - glDeleteBuffers(1, &ebo_); - ebo_ = 0; - } - - if (program_id_ != 0) { - glDeleteProgram(program_id_); - program_id_ = 0; - } - - is_initialized_ = false; - window_ = nullptr; - renderer_ = nullptr; - back_buffer_ = nullptr; - } - -} // namespace Rendering diff --git a/source/rendering/opengl/opengl_shader.hpp b/source/rendering/opengl/opengl_shader.hpp deleted file mode 100644 index d130fe7..0000000 --- a/source/rendering/opengl/opengl_shader.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include "../shader_backend.hpp" - -#ifdef __APPLE__ -#include -#else -#include -#endif - -namespace Rendering { - - /** - * @brief Backend de shaders usando OpenGL 3.3 Core Profile - * - * Implementa el renderizado de shaders usando APIs modernas de OpenGL: - * - VAO (Vertex Array Objects) - * - VBO (Vertex Buffer Objects) - * - Shaders GLSL #version 330 core - */ - class OpenGLShader : public ShaderBackend { - public: - OpenGLShader() = default; - ~OpenGLShader() override; - - auto init(SDL_Window* window, - SDL_Texture* texture, - const std::string& vertex_source, - const std::string& fragment_source) -> bool override; - - void render() override; - void setTextureSize(float width, float height) override; - void cleanup() final; - [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } - - private: - // Funciones auxiliares - auto initGLExtensions() -> bool; - static auto compileShader(const std::string& source, GLenum shader_type) -> GLuint; - static auto linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint; - void createQuadGeometry(); - static auto getTextureID(SDL_Texture* texture) -> GLuint; - static void checkGLError(const char* operation); - - // Estado SDL - SDL_Window* window_ = nullptr; - SDL_Renderer* renderer_ = nullptr; - SDL_Texture* back_buffer_ = nullptr; - - // Estado OpenGL - GLuint program_id_ = 0; - GLuint vao_ = 0; // Vertex Array Object - GLuint vbo_ = 0; // Vertex Buffer Object - GLuint ebo_ = 0; // Element Buffer Object - - // Ubicaciones de uniforms - GLint texture_size_location_ = -1; - - // Tamaños - int window_width_ = 0; - int window_height_ = 0; - float texture_width_ = 0.0F; - float texture_height_ = 0.0F; - - // Estado - bool is_initialized_ = false; - -#ifndef __APPLE__ - // Punteros a funciones OpenGL en Windows/Linux - PFNGLCREATESHADERPROC glCreateShader = nullptr; - PFNGLSHADERSOURCEPROC glShaderSource = nullptr; - PFNGLCOMPILESHADERPROC glCompileShader = nullptr; - PFNGLGETSHADERIVPROC glGetShaderiv = nullptr; - PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr; - PFNGLDELETESHADERPROC glDeleteShader = nullptr; - PFNGLATTACHSHADERPROC glAttachShader = nullptr; - PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr; - PFNGLLINKPROGRAMPROC glLinkProgram = nullptr; - PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr; - PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr; - PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr; - PFNGLUSEPROGRAMPROC glUseProgram = nullptr; - PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr; - PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr; - PFNGLUNIFORM2FPROC glUniform2f = nullptr; - PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr; - PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr; - PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr; - PFNGLGENBUFFERSPROC glGenBuffers = nullptr; - PFNGLBINDBUFFERPROC glBindBuffer = nullptr; - PFNGLBUFFERDATAPROC glBufferData = nullptr; - PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr; - PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr; - PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; -#endif - }; - -} // namespace Rendering diff --git a/source/rendering/sdl3gpu/postfx_frag_spv.h b/source/rendering/sdl3gpu/postfx_frag_spv.h new file mode 100644 index 0000000..dbd2688 --- /dev/null +++ b/source/rendering/sdl3gpu/postfx_frag_spv.h @@ -0,0 +1,10341 @@ +#pragma once +#include +#include +static const uint8_t kpostfx_frag_spv[] = { + 0x03, + 0x02, + 0x23, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x0b, + 0x00, + 0x0d, + 0x00, + 0xbc, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x02, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x02, + 0x00, + 0x32, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x06, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x47, + 0x4c, + 0x53, + 0x4c, + 0x2e, + 0x73, + 0x74, + 0x64, + 0x2e, + 0x34, + 0x35, + 0x30, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x08, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0x97, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x03, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xc2, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x0a, + 0x00, + 0x47, + 0x4c, + 0x5f, + 0x47, + 0x4f, + 0x4f, + 0x47, + 0x4c, + 0x45, + 0x5f, + 0x63, + 0x70, + 0x70, + 0x5f, + 0x73, + 0x74, + 0x79, + 0x6c, + 0x65, + 0x5f, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x5f, + 0x64, + 0x69, + 0x72, + 0x65, + 0x63, + 0x74, + 0x69, + 0x76, + 0x65, + 0x00, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x47, + 0x4c, + 0x5f, + 0x47, + 0x4f, + 0x4f, + 0x47, + 0x4c, + 0x45, + 0x5f, + 0x69, + 0x6e, + 0x63, + 0x6c, + 0x75, + 0x64, + 0x65, + 0x5f, + 0x64, + 0x69, + 0x72, + 0x65, + 0x63, + 0x74, + 0x69, + 0x76, + 0x65, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x72, + 0x67, + 0x62, + 0x5f, + 0x74, + 0x6f, + 0x5f, + 0x79, + 0x63, + 0x63, + 0x28, + 0x76, + 0x66, + 0x33, + 0x3b, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x72, + 0x67, + 0x62, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x5f, + 0x74, + 0x6f, + 0x5f, + 0x72, + 0x67, + 0x62, + 0x28, + 0x76, + 0x66, + 0x33, + 0x3b, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x46, + 0x00, + 0x00, + 0x00, + 0x63, + 0x62, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x63, + 0x72, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x75, + 0x76, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x76, + 0x5f, + 0x75, + 0x76, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x50, + 0x6f, + 0x73, + 0x74, + 0x46, + 0x58, + 0x55, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x73, + 0x00, + 0x00, + 0x06, + 0x00, + 0x08, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x76, + 0x69, + 0x67, + 0x6e, + 0x65, + 0x74, + 0x74, + 0x65, + 0x5f, + 0x73, + 0x74, + 0x72, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x63, + 0x68, + 0x72, + 0x6f, + 0x6d, + 0x61, + 0x5f, + 0x73, + 0x74, + 0x72, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x00, + 0x06, + 0x00, + 0x08, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x73, + 0x63, + 0x61, + 0x6e, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x5f, + 0x73, + 0x74, + 0x72, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x73, + 0x63, + 0x72, + 0x65, + 0x65, + 0x6e, + 0x5f, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x73, + 0x6b, + 0x5f, + 0x73, + 0x74, + 0x72, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x67, + 0x61, + 0x6d, + 0x6d, + 0x61, + 0x5f, + 0x73, + 0x74, + 0x72, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x00, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x63, + 0x75, + 0x72, + 0x76, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x62, + 0x6c, + 0x65, + 0x65, + 0x64, + 0x69, + 0x6e, + 0x67, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x72, + 0x73, + 0x71, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x83, + 0x00, + 0x00, + 0x00, + 0x64, + 0x69, + 0x73, + 0x74, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x00, + 0x62, + 0x61, + 0x72, + 0x72, + 0x65, + 0x6c, + 0x53, + 0x63, + 0x61, + 0x6c, + 0x65, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0x6f, + 0x75, + 0x74, + 0x5f, + 0x63, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0x62, + 0x61, + 0x73, + 0x65, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x74, + 0x77, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xc8, + 0x00, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xcb, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x5f, + 0x6c, + 0x32, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xd4, + 0x00, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xd7, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x5f, + 0x6c, + 0x31, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xdf, + 0x00, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xe2, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x5f, + 0x72, + 0x31, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xea, + 0x00, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xed, + 0x00, + 0x00, + 0x00, + 0x79, + 0x63, + 0x63, + 0x5f, + 0x72, + 0x32, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0xf5, + 0x00, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x63, + 0x6f, + 0x6c, + 0x6f, + 0x75, + 0x72, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x12, + 0x01, + 0x00, + 0x00, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x1b, + 0x01, + 0x00, + 0x00, + 0x63, + 0x61, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x37, + 0x01, + 0x00, + 0x00, + 0x6c, + 0x69, + 0x6e, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x42, + 0x01, + 0x00, + 0x00, + 0x74, + 0x65, + 0x78, + 0x48, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x48, + 0x01, + 0x00, + 0x00, + 0x73, + 0x63, + 0x61, + 0x6c, + 0x65, + 0x59, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x4e, + 0x01, + 0x00, + 0x00, + 0x73, + 0x63, + 0x72, + 0x65, + 0x65, + 0x6e, + 0x59, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x54, + 0x01, + 0x00, + 0x00, + 0x70, + 0x6f, + 0x73, + 0x49, + 0x6e, + 0x52, + 0x6f, + 0x77, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x58, + 0x01, + 0x00, + 0x00, + 0x73, + 0x63, + 0x61, + 0x6e, + 0x4c, + 0x69, + 0x6e, + 0x65, + 0x44, + 0x59, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x5d, + 0x01, + 0x00, + 0x00, + 0x73, + 0x63, + 0x61, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x74, + 0x01, + 0x00, + 0x00, + 0x65, + 0x6e, + 0x63, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x7f, + 0x01, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x83, + 0x01, + 0x00, + 0x00, + 0x76, + 0x69, + 0x67, + 0x6e, + 0x65, + 0x74, + 0x74, + 0x65, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x95, + 0x01, + 0x00, + 0x00, + 0x77, + 0x68, + 0x69, + 0x63, + 0x68, + 0x4d, + 0x61, + 0x73, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x97, + 0x01, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x46, + 0x72, + 0x61, + 0x67, + 0x43, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x73, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x03, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x97, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x03, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x04, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x87, + 0x16, + 0x99, + 0x3e, + 0x15, + 0x00, + 0x04, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x45, + 0x16, + 0x3f, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0xd5, + 0x78, + 0xe9, + 0x3d, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x56, + 0x0e, + 0x2d, + 0xbe, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x00, + 0xd5, + 0x78, + 0xa9, + 0x3e, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x87, + 0xd6, + 0x3e, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x54, + 0xe3, + 0xa5, + 0x3d, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0xbc, + 0x74, + 0xb3, + 0x3f, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x20, + 0xb0, + 0x3e, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0xb4, + 0xc8, + 0x36, + 0x3f, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x00, + 0xe5, + 0xd0, + 0xe2, + 0x3f, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x3f, + 0x17, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x0a, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x70, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x70, + 0x00, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x02, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x00, + 0xcd, + 0xcc, + 0x4c, + 0x3d, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x00, + 0xcd, + 0xcc, + 0xcc, + 0x3d, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x85, + 0x6b, + 0x3e, + 0x17, + 0x00, + 0x04, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0xa9, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0xa9, + 0x00, + 0x00, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x07, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xab, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x09, + 0x00, + 0xb1, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x03, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xb1, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0xb3, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0xb3, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0xb9, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0xc1, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x04, + 0x00, + 0xc3, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x01, + 0x00, + 0x00, + 0x0a, + 0xd7, + 0xa3, + 0x3b, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x31, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x9a, + 0x99, + 0x19, + 0x40, + 0x2c, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x01, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x49, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x61, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x40, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x64, + 0x01, + 0x00, + 0x00, + 0x8f, + 0xc2, + 0xf5, + 0x3d, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x66, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x60, + 0x40, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x69, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x76, + 0x01, + 0x00, + 0x00, + 0x2f, + 0xba, + 0xe8, + 0x3e, + 0x2c, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x77, + 0x01, + 0x00, + 0x00, + 0x76, + 0x01, + 0x00, + 0x00, + 0x76, + 0x01, + 0x00, + 0x00, + 0x76, + 0x01, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x8f, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x96, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x96, + 0x01, + 0x00, + 0x00, + 0x97, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x98, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9b, + 0x01, + 0x00, + 0x00, + 0xaa, + 0xaa, + 0xaa, + 0x3e, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9f, + 0x01, + 0x00, + 0x00, + 0xcd, + 0xcc, + 0x4c, + 0x3f, + 0x2c, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xa0, + 0x01, + 0x00, + 0x00, + 0x9f, + 0x01, + 0x00, + 0x00, + 0x9f, + 0x01, + 0x00, + 0x00, + 0x9f, + 0x01, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xa8, + 0x01, + 0x00, + 0x00, + 0xaa, + 0xaa, + 0x2a, + 0x3f, + 0x36, + 0x00, + 0x05, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xc8, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xcb, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xd4, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xd7, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xdf, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xe2, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xea, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xed, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0xf5, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x12, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x37, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x42, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x48, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x54, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x58, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x74, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x83, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x95, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x00, + 0xba, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x79, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x94, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x83, + 0x00, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x92, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x93, + 0x00, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x00, + 0x92, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x94, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x93, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x95, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x96, + 0x00, + 0x00, + 0x00, + 0x95, + 0x00, + 0x00, + 0x00, + 0x94, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x96, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x97, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x98, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x99, + 0x00, + 0x00, + 0x00, + 0x98, + 0x00, + 0x00, + 0x00, + 0x97, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x99, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x9a, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9b, + 0x00, + 0x00, + 0x00, + 0x9a, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9c, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x9b, + 0x00, + 0x00, + 0x00, + 0xbe, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x9d, + 0x00, + 0x00, + 0x00, + 0x9c, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0xa8, + 0x00, + 0x04, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x9e, + 0x00, + 0x00, + 0x00, + 0x9d, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0xa0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0x9e, + 0x00, + 0x00, + 0x00, + 0x9f, + 0x00, + 0x00, + 0x00, + 0xa0, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x9f, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0xa1, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x00, + 0x00, + 0x00, + 0xa1, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xa3, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x00, + 0x00, + 0x00, + 0xbe, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0xa4, + 0x00, + 0x00, + 0x00, + 0xa3, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xa0, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa0, + 0x00, + 0x00, + 0x00, + 0xf5, + 0x00, + 0x07, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0xa5, + 0x00, + 0x00, + 0x00, + 0x9d, + 0x00, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x00, + 0xa4, + 0x00, + 0x00, + 0x00, + 0x9f, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0xa7, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0xa5, + 0x00, + 0x00, + 0x00, + 0xa6, + 0x00, + 0x00, + 0x00, + 0xa7, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa6, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0xab, + 0x00, + 0x00, + 0x00, + 0xfd, + 0x00, + 0x01, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa7, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xad, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xae, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xaf, + 0x00, + 0x00, + 0x00, + 0xad, + 0x00, + 0x00, + 0x00, + 0xae, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0xaf, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xb5, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xb6, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xb7, + 0x00, + 0x00, + 0x00, + 0xb5, + 0x00, + 0x00, + 0x00, + 0xb6, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb8, + 0x00, + 0x00, + 0x00, + 0xb7, + 0x00, + 0x00, + 0x00, + 0xb7, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0xb8, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0xba, + 0x00, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0xb9, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xbb, + 0x00, + 0x00, + 0x00, + 0xba, + 0x00, + 0x00, + 0x00, + 0xba, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0xbc, + 0x00, + 0x00, + 0x00, + 0xbb, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0xbc, + 0x00, + 0x00, + 0x00, + 0xbd, + 0x00, + 0x00, + 0x00, + 0x19, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xbd, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x04, + 0x00, + 0xb1, + 0x00, + 0x00, + 0x00, + 0xc2, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x00, + 0x00, + 0x00, + 0x67, + 0x00, + 0x05, + 0x00, + 0xc3, + 0x00, + 0x00, + 0x00, + 0xc4, + 0x00, + 0x00, + 0x00, + 0xc2, + 0x00, + 0x00, + 0x00, + 0xc1, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x00, + 0x00, + 0x00, + 0xc4, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xc9, + 0x00, + 0x00, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xc8, + 0x00, + 0x00, + 0x00, + 0xc9, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xca, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0xc8, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0xca, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xcc, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xcd, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xcf, + 0x00, + 0x00, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x00, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0xcf, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xd1, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xd2, + 0x00, + 0x00, + 0x00, + 0xcd, + 0x00, + 0x00, + 0x00, + 0xd1, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xd3, + 0x00, + 0x00, + 0x00, + 0xcc, + 0x00, + 0x00, + 0x00, + 0xd2, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xd5, + 0x00, + 0x00, + 0x00, + 0xd3, + 0x00, + 0x00, + 0x00, + 0xd3, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xd4, + 0x00, + 0x00, + 0x00, + 0xd5, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xd6, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0xd4, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xcb, + 0x00, + 0x00, + 0x00, + 0xd6, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xd8, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xd9, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xda, + 0x00, + 0x00, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xdb, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0xda, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x00, + 0x00, + 0x00, + 0xdb, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x00, + 0x00, + 0x00, + 0xd9, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xde, + 0x00, + 0x00, + 0x00, + 0xd8, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xe0, + 0x00, + 0x00, + 0x00, + 0xde, + 0x00, + 0x00, + 0x00, + 0xde, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xdf, + 0x00, + 0x00, + 0x00, + 0xe0, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xe1, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0xdf, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xd7, + 0x00, + 0x00, + 0x00, + 0xe1, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xe3, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xe4, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xe5, + 0x00, + 0x00, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xe6, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0xe5, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xe7, + 0x00, + 0x00, + 0x00, + 0xe6, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xe8, + 0x00, + 0x00, + 0x00, + 0xe4, + 0x00, + 0x00, + 0x00, + 0xe7, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xe9, + 0x00, + 0x00, + 0x00, + 0xe3, + 0x00, + 0x00, + 0x00, + 0xe8, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xeb, + 0x00, + 0x00, + 0x00, + 0xe9, + 0x00, + 0x00, + 0x00, + 0xe9, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xea, + 0x00, + 0x00, + 0x00, + 0xeb, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xec, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0xea, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xe2, + 0x00, + 0x00, + 0x00, + 0xec, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0xee, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xef, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xf0, + 0x00, + 0x00, + 0x00, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xf1, + 0x00, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0xf0, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xf2, + 0x00, + 0x00, + 0x00, + 0xf1, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xf3, + 0x00, + 0x00, + 0x00, + 0xef, + 0x00, + 0x00, + 0x00, + 0xf2, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xf4, + 0x00, + 0x00, + 0x00, + 0xee, + 0x00, + 0x00, + 0x00, + 0xf3, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xf6, + 0x00, + 0x00, + 0x00, + 0xf4, + 0x00, + 0x00, + 0x00, + 0xf4, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xf5, + 0x00, + 0x00, + 0x00, + 0xf6, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0xf5, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xed, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x00, + 0x00, + 0xcb, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x07, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x00, + 0x00, + 0xd7, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x07, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xfb, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xfc, + 0x00, + 0x00, + 0x00, + 0xfb, + 0x00, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xfd, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x00, + 0x00, + 0xfc, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x07, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0xfd, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0xe2, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x07, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x04, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0xce, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x05, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x04, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0xed, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x07, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x07, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x08, + 0x01, + 0x00, + 0x00, + 0x05, + 0x01, + 0x00, + 0x00, + 0x07, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x01, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x01, + 0x00, + 0x00, + 0x08, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x01, + 0x00, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x0c, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x01, + 0x00, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x0e, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x11, + 0x01, + 0x00, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x13, + 0x01, + 0x00, + 0x00, + 0xc7, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x12, + 0x01, + 0x00, + 0x00, + 0x13, + 0x01, + 0x00, + 0x00, + 0x39, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x14, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x12, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x15, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0xb9, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x16, + 0x01, + 0x00, + 0x00, + 0x15, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x17, + 0x01, + 0x00, + 0x00, + 0x16, + 0x01, + 0x00, + 0x00, + 0x16, + 0x01, + 0x00, + 0x00, + 0x16, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x18, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x11, + 0x01, + 0x00, + 0x00, + 0x14, + 0x01, + 0x00, + 0x00, + 0x17, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x18, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xbe, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x19, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x01, + 0x00, + 0x00, + 0xb0, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xbe, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x1b, + 0x01, + 0x00, + 0x00, + 0x20, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x22, + 0x01, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x23, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x24, + 0x01, + 0x00, + 0x00, + 0x23, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x25, + 0x01, + 0x00, + 0x00, + 0x22, + 0x01, + 0x00, + 0x00, + 0x24, + 0x01, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0x26, + 0x01, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x25, + 0x01, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x27, + 0x01, + 0x00, + 0x00, + 0x26, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x28, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x28, + 0x01, + 0x00, + 0x00, + 0x27, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0x29, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x01, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x01, + 0x00, + 0x00, + 0x2b, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x01, + 0x00, + 0x00, + 0x2a, + 0x01, + 0x00, + 0x00, + 0x2c, + 0x01, + 0x00, + 0x00, + 0x57, + 0x00, + 0x05, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x01, + 0x00, + 0x00, + 0x29, + 0x01, + 0x00, + 0x00, + 0x2d, + 0x01, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x01, + 0x00, + 0x00, + 0x2e, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x30, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x30, + 0x01, + 0x00, + 0x00, + 0x2f, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x32, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x31, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x33, + 0x01, + 0x00, + 0x00, + 0x32, + 0x01, + 0x00, + 0x00, + 0xba, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x34, + 0x01, + 0x00, + 0x00, + 0x33, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0x34, + 0x01, + 0x00, + 0x00, + 0x35, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x35, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x38, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x38, + 0x01, + 0x00, + 0x00, + 0x3a, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x37, + 0x01, + 0x00, + 0x00, + 0x3b, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x01, + 0x00, + 0x00, + 0x37, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x31, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, + 0x00, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x41, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x01, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x41, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0xb2, + 0x00, + 0x00, + 0x00, + 0x43, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x04, + 0x00, + 0xb1, + 0x00, + 0x00, + 0x00, + 0x44, + 0x01, + 0x00, + 0x00, + 0x43, + 0x01, + 0x00, + 0x00, + 0x67, + 0x00, + 0x05, + 0x00, + 0xc3, + 0x00, + 0x00, + 0x00, + 0x45, + 0x01, + 0x00, + 0x00, + 0x44, + 0x01, + 0x00, + 0x00, + 0xc1, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x72, + 0x00, + 0x00, + 0x00, + 0x46, + 0x01, + 0x00, + 0x00, + 0x45, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x47, + 0x01, + 0x00, + 0x00, + 0x46, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x42, + 0x01, + 0x00, + 0x00, + 0x47, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x49, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4b, + 0x01, + 0x00, + 0x00, + 0x4a, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x01, + 0x00, + 0x00, + 0x42, + 0x01, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4d, + 0x01, + 0x00, + 0x00, + 0x4b, + 0x01, + 0x00, + 0x00, + 0x4c, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x48, + 0x01, + 0x00, + 0x00, + 0x4d, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x01, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x01, + 0x00, + 0x00, + 0x4f, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x51, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x49, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x52, + 0x01, + 0x00, + 0x00, + 0x51, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x53, + 0x01, + 0x00, + 0x00, + 0x50, + 0x01, + 0x00, + 0x00, + 0x52, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x4e, + 0x01, + 0x00, + 0x00, + 0x53, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x55, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x56, + 0x01, + 0x00, + 0x00, + 0x48, + 0x01, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x57, + 0x01, + 0x00, + 0x00, + 0x55, + 0x01, + 0x00, + 0x00, + 0x56, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x54, + 0x01, + 0x00, + 0x00, + 0x57, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x59, + 0x01, + 0x00, + 0x00, + 0x54, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x01, + 0x00, + 0x00, + 0x48, + 0x01, + 0x00, + 0x00, + 0x88, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5b, + 0x01, + 0x00, + 0x00, + 0x59, + 0x01, + 0x00, + 0x00, + 0x5a, + 0x01, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x01, + 0x00, + 0x00, + 0x5b, + 0x01, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x58, + 0x01, + 0x00, + 0x00, + 0x5c, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x01, + 0x00, + 0x00, + 0x58, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5f, + 0x01, + 0x00, + 0x00, + 0x58, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x5e, + 0x01, + 0x00, + 0x00, + 0x5f, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x62, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x61, + 0x01, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x63, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x07, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x65, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x00, + 0x63, + 0x01, + 0x00, + 0x00, + 0x64, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x67, + 0x01, + 0x00, + 0x00, + 0x65, + 0x01, + 0x00, + 0x00, + 0x66, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x5d, + 0x01, + 0x00, + 0x00, + 0x67, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x68, + 0x01, + 0x00, + 0x00, + 0x5d, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x69, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x6b, + 0x01, + 0x00, + 0x00, + 0x6a, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x68, + 0x01, + 0x00, + 0x00, + 0x6b, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x01, + 0x00, + 0x00, + 0x6d, + 0x01, + 0x00, + 0x00, + 0x6c, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x6e, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x6f, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x31, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x70, + 0x01, + 0x00, + 0x00, + 0x6f, + 0x01, + 0x00, + 0x00, + 0xba, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x71, + 0x01, + 0x00, + 0x00, + 0x70, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0x73, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0x71, + 0x01, + 0x00, + 0x00, + 0x72, + 0x01, + 0x00, + 0x00, + 0x73, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x72, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x75, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x78, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x75, + 0x01, + 0x00, + 0x00, + 0x77, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x74, + 0x01, + 0x00, + 0x00, + 0x78, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x79, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x01, + 0x00, + 0x00, + 0x74, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x31, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x01, + 0x00, + 0x00, + 0x7b, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x7d, + 0x01, + 0x00, + 0x00, + 0x7c, + 0x01, + 0x00, + 0x00, + 0x7c, + 0x01, + 0x00, + 0x00, + 0x7c, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x79, + 0x01, + 0x00, + 0x00, + 0x7a, + 0x01, + 0x00, + 0x00, + 0x7d, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x7e, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0x73, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x73, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x80, + 0x01, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x81, + 0x01, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x82, + 0x01, + 0x00, + 0x00, + 0x80, + 0x01, + 0x00, + 0x00, + 0x81, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x7f, + 0x01, + 0x00, + 0x00, + 0x82, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x84, + 0x01, + 0x00, + 0x00, + 0x7f, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x69, + 0x00, + 0x00, + 0x00, + 0x85, + 0x01, + 0x00, + 0x00, + 0x7f, + 0x01, + 0x00, + 0x00, + 0x94, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x86, + 0x01, + 0x00, + 0x00, + 0x84, + 0x01, + 0x00, + 0x00, + 0x85, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x87, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0xc1, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x88, + 0x01, + 0x00, + 0x00, + 0x87, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x89, + 0x01, + 0x00, + 0x00, + 0x86, + 0x01, + 0x00, + 0x00, + 0x88, + 0x01, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x89, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x83, + 0x01, + 0x00, + 0x00, + 0x8a, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x8b, + 0x01, + 0x00, + 0x00, + 0x83, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x8b, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x8d, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x01, + 0x00, + 0x00, + 0x8d, + 0x01, + 0x00, + 0x00, + 0x8c, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x8e, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x8f, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x91, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0xba, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0x92, + 0x01, + 0x00, + 0x00, + 0x91, + 0x01, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0x94, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0x92, + 0x01, + 0x00, + 0x00, + 0x93, + 0x01, + 0x00, + 0x00, + 0x94, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x93, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x98, + 0x01, + 0x00, + 0x00, + 0x99, + 0x01, + 0x00, + 0x00, + 0x97, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9a, + 0x01, + 0x00, + 0x00, + 0x99, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9c, + 0x01, + 0x00, + 0x00, + 0x9a, + 0x01, + 0x00, + 0x00, + 0x9b, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x9d, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x9c, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x95, + 0x01, + 0x00, + 0x00, + 0x9d, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0xa0, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xa1, + 0x01, + 0x00, + 0x00, + 0x95, + 0x01, + 0x00, + 0x00, + 0xb8, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x01, + 0x00, + 0x00, + 0xa1, + 0x01, + 0x00, + 0x00, + 0x9b, + 0x01, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0xa4, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0xa2, + 0x01, + 0x00, + 0x00, + 0xa3, + 0x01, + 0x00, + 0x00, + 0xa6, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa3, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0xa5, + 0x01, + 0x00, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xa5, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xa4, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa6, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xa7, + 0x01, + 0x00, + 0x00, + 0x95, + 0x01, + 0x00, + 0x00, + 0xb8, + 0x00, + 0x05, + 0x00, + 0x77, + 0x00, + 0x00, + 0x00, + 0xa9, + 0x01, + 0x00, + 0x00, + 0xa7, + 0x01, + 0x00, + 0x00, + 0xa8, + 0x01, + 0x00, + 0x00, + 0xf7, + 0x00, + 0x03, + 0x00, + 0xab, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfa, + 0x00, + 0x04, + 0x00, + 0xa9, + 0x01, + 0x00, + 0x00, + 0xaa, + 0x01, + 0x00, + 0x00, + 0xad, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xaa, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0xac, + 0x01, + 0x00, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xac, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xab, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xad, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0xae, + 0x01, + 0x00, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xae, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xab, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xab, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0xa4, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0xa4, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xaf, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb0, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb1, + 0x01, + 0x00, + 0x00, + 0x9e, + 0x01, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb2, + 0x01, + 0x00, + 0x00, + 0xb0, + 0x01, + 0x00, + 0x00, + 0xb1, + 0x01, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x74, + 0x00, + 0x00, + 0x00, + 0xb3, + 0x01, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x00, + 0x8f, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xb4, + 0x01, + 0x00, + 0x00, + 0xb3, + 0x01, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb5, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x01, + 0x00, + 0x00, + 0xb4, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb6, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0xaf, + 0x01, + 0x00, + 0x00, + 0xb2, + 0x01, + 0x00, + 0x00, + 0xb5, + 0x01, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0xb6, + 0x01, + 0x00, + 0x00, + 0xf9, + 0x00, + 0x02, + 0x00, + 0x94, + 0x01, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x94, + 0x01, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0xb7, + 0x01, + 0x00, + 0x00, + 0x10, + 0x01, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xb8, + 0x01, + 0x00, + 0x00, + 0xb7, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xb9, + 0x01, + 0x00, + 0x00, + 0xb7, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0xba, + 0x01, + 0x00, + 0x00, + 0xb7, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x07, + 0x00, + 0xa8, + 0x00, + 0x00, + 0x00, + 0xbb, + 0x01, + 0x00, + 0x00, + 0xb8, + 0x01, + 0x00, + 0x00, + 0xb9, + 0x01, + 0x00, + 0x00, + 0xba, + 0x01, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0xaa, + 0x00, + 0x00, + 0x00, + 0xbb, + 0x01, + 0x00, + 0x00, + 0xfd, + 0x00, + 0x01, + 0x00, + 0x38, + 0x00, + 0x01, + 0x00, + 0x36, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x03, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x02, + 0x00, + 0x40, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x01, + 0x00, + 0x36, + 0x00, + 0x05, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x03, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x46, + 0x00, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x00, + 0x83, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x00, + 0x81, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x08, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x02, + 0x00, + 0x66, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x01, + 0x00}; +static const size_t kpostfx_frag_spv_size = 10336; diff --git a/source/rendering/sdl3gpu/postfx_vert_spv.h b/source/rendering/sdl3gpu/postfx_vert_spv.h new file mode 100644 index 0000000..1be581e --- /dev/null +++ b/source/rendering/sdl3gpu/postfx_vert_spv.h @@ -0,0 +1,1449 @@ +#pragma once +#include +#include +static const uint8_t kpostfx_vert_spv[] = { + 0x03, + 0x02, + 0x23, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x0b, + 0x00, + 0x0d, + 0x00, + 0x33, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x02, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x06, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x47, + 0x4c, + 0x53, + 0x4c, + 0x2e, + 0x73, + 0x74, + 0x64, + 0x2e, + 0x34, + 0x35, + 0x30, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xc2, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x0a, + 0x00, + 0x47, + 0x4c, + 0x5f, + 0x47, + 0x4f, + 0x4f, + 0x47, + 0x4c, + 0x45, + 0x5f, + 0x63, + 0x70, + 0x70, + 0x5f, + 0x73, + 0x74, + 0x79, + 0x6c, + 0x65, + 0x5f, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x5f, + 0x64, + 0x69, + 0x72, + 0x65, + 0x63, + 0x74, + 0x69, + 0x76, + 0x65, + 0x00, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x47, + 0x4c, + 0x5f, + 0x47, + 0x4f, + 0x4f, + 0x47, + 0x4c, + 0x45, + 0x5f, + 0x69, + 0x6e, + 0x63, + 0x6c, + 0x75, + 0x64, + 0x65, + 0x5f, + 0x64, + 0x69, + 0x72, + 0x65, + 0x63, + 0x74, + 0x69, + 0x76, + 0x65, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x50, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x53, + 0x69, + 0x7a, + 0x65, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x43, + 0x6c, + 0x69, + 0x70, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x43, + 0x75, + 0x6c, + 0x6c, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x5f, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x61, + 0x62, + 0x6c, + 0x65, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x04, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x76, + 0x5f, + 0x75, + 0x76, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x05, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x61, + 0x62, + 0x6c, + 0x65, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x03, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x05, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x04, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x03, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x04, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x04, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x06, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x04, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x04, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x04, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xbf, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x40, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x06, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x19, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x19, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x3f, + 0x20, + 0x00, + 0x04, + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x04, + 0x00, + 0x28, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x28, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x04, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x05, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x06, + 0x00, + 0x12, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x05, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x00, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x04, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x05, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x05, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x04, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x03, + 0x00, + 0x29, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x00, + 0xfd, + 0x00, + 0x01, + 0x00, + 0x38, + 0x00, + 0x01, + 0x00}; +static const size_t kpostfx_vert_spv_size = 1444; diff --git a/source/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/rendering/sdl3gpu/sdl3gpu_shader.cpp new file mode 100644 index 0000000..b4e0860 --- /dev/null +++ b/source/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -0,0 +1,720 @@ +#include "rendering/sdl3gpu/sdl3gpu_shader.hpp" + +#include + +#include // std::min, std::max, std::floor +#include // std::floor +#include // memcpy, strlen + +#ifndef __APPLE__ +#include "rendering/sdl3gpu/postfx_frag_spv.h" +#include "rendering/sdl3gpu/postfx_vert_spv.h" +#endif + +#ifdef __APPLE__ +// ============================================================================ +// MSL shaders (Metal Shading Language) — macOS +// ============================================================================ + +// NOLINTBEGIN(readability-identifier-naming) +static const char* POSTFX_VERT_MSL = R"( +#include +using namespace metal; + +struct PostVOut { + float4 pos [[position]]; + float2 uv; +}; + +vertex PostVOut postfx_vs(uint vid [[vertex_id]]) { + const float2 positions[3] = { {-1.0, -1.0}, {3.0, -1.0}, {-1.0, 3.0} }; + const float2 uvs[3] = { { 0.0, 1.0}, {2.0, 1.0}, { 0.0,-1.0} }; + PostVOut out; + out.pos = float4(positions[vid], 0.0, 1.0); + out.uv = uvs[vid]; + return out; +} +)"; + +static const char* POSTFX_FRAG_MSL = R"( +#include +using namespace metal; + +struct PostVOut { + float4 pos [[position]]; + float2 uv; +}; + +struct PostFXUniforms { + float vignette_strength; + float chroma_strength; + float scanline_strength; + float screen_height; + float mask_strength; + float gamma_strength; + float curvature; + float bleeding; + float pixel_scale; + float time; + float oversample; // 1.0 = sin SS, 3.0 = 3× supersampling + float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz +}; + +// YCbCr helpers for NTSC bleeding +static float3 rgb_to_ycc(float3 rgb) { + return float3( + 0.299f*rgb.r + 0.587f*rgb.g + 0.114f*rgb.b, + -0.169f*rgb.r - 0.331f*rgb.g + 0.500f*rgb.b + 0.5f, + 0.500f*rgb.r - 0.419f*rgb.g - 0.081f*rgb.b + 0.5f + ); +} +static float3 ycc_to_rgb(float3 ycc) { + float y = ycc.x; + float cb = ycc.y - 0.5f; + float cr = ycc.z - 0.5f; + return clamp(float3( + y + 1.402f*cr, + y - 0.344f*cb - 0.714f*cr, + y + 1.772f*cb + ), 0.0f, 1.0f); +} + +fragment float4 postfx_fs(PostVOut in [[stage_in]], + texture2d scene [[texture(0)]], + sampler samp [[sampler(0)]], + constant PostFXUniforms& u [[buffer(0)]]) { + float2 uv = in.uv; + + // Curvatura barrel CRT + if (u.curvature > 0.0f) { + float2 c = uv - 0.5f; + float rsq = dot(c, c); + float2 dist = float2(0.05f, 0.1f) * u.curvature; + float2 barrelScale = 1.0f - 0.23f * dist; + c += c * (dist * rsq); + c *= barrelScale; + if (abs(c.x) >= 0.5f || abs(c.y) >= 0.5f) { + return float4(0.0f, 0.0f, 0.0f, 1.0f); + } + uv = c + 0.5f; + } + + // Muestra base + float3 base = scene.sample(samp, uv).rgb; + + // Sangrado NTSC — difuminado horizontal de crominancia. + // step = 1 pixel de juego en espacio UV (corrige SS: scene.get_width() = game_w * oversample). + float3 colour; + if (u.bleeding > 0.0f) { + float tw = float(scene.get_width()); + float step = u.oversample / tw; // 1 pixel lógico en UV + float3 ycc = rgb_to_ycc(base); + float3 ycc_l2 = rgb_to_ycc(scene.sample(samp, uv - float2(2.0f*step, 0.0f)).rgb); + float3 ycc_l1 = rgb_to_ycc(scene.sample(samp, uv - float2(1.0f*step, 0.0f)).rgb); + float3 ycc_r1 = rgb_to_ycc(scene.sample(samp, uv + float2(1.0f*step, 0.0f)).rgb); + float3 ycc_r2 = rgb_to_ycc(scene.sample(samp, uv + float2(2.0f*step, 0.0f)).rgb); + ycc.yz = (ycc_l2.yz + ycc_l1.yz*2.0f + ycc.yz*2.0f + ycc_r1.yz*2.0f + ycc_r2.yz) / 8.0f; + colour = mix(base, ycc_to_rgb(ycc), u.bleeding); + } else { + colour = base; + } + + // Aberración cromática (drift animado con time para efecto NTSC real) + float ca = u.chroma_strength * 0.005f * (1.0f + 0.15f * sin(u.time * 7.3f)); + colour.r = scene.sample(samp, uv + float2(ca, 0.0f)).r; + colour.b = scene.sample(samp, uv - float2(ca, 0.0f)).b; + + // Corrección gamma (linealizar antes de scanlines, codificar después) + if (u.gamma_strength > 0.0f) { + float3 lin = pow(colour, float3(2.4f)); + colour = mix(colour, lin, u.gamma_strength); + } + + // Scanlines — 1 pixel físico oscuro por fila lógica. + // Usa uv.y (independiente del offset de letterbox) con pixel_scale para + // calcular la posición dentro de la fila en coordenadas físicas. + // 3x: 1 dark + 2 bright. 4x: 1 dark + 3 bright. + // bright=3.5×, dark floor=0.42 (mantiene aspecto CRT original). + if (u.scanline_strength > 0.0f) { + float ps = max(1.0f, round(u.pixel_scale)); + float frac_in_row = fract(uv.y * u.screen_height); + float row_pos = floor(frac_in_row * ps); + float is_dark = step(ps - 1.0f, row_pos); + float scan = mix(3.5f, 0.42f, is_dark); + colour *= mix(1.0f, scan, u.scanline_strength); + } + + if (u.gamma_strength > 0.0f) { + float3 enc = pow(colour, float3(1.0f/2.2f)); + colour = mix(colour, enc, u.gamma_strength); + } + + // Viñeta + float2 d = uv - 0.5f; + float vignette = 1.0f - dot(d, d) * u.vignette_strength; + colour *= clamp(vignette, 0.0f, 1.0f); + + // Máscara de fósforo RGB — después de scanlines (orden original): + // filas brillantes saturadas → máscara invisible, filas oscuras → RGB visible. + if (u.mask_strength > 0.0f) { + float whichMask = fract(in.pos.x * 0.3333333f); + float3 mask = float3(0.80f); + if (whichMask < 0.3333333f) mask.x = 1.0f; + else if (whichMask < 0.6666667f) mask.y = 1.0f; + else mask.z = 1.0f; + colour = mix(colour, colour * mask, u.mask_strength); + } + + // Parpadeo de fósforo CRT (~50 Hz) + if (u.flicker > 0.0f) { + float flicker_wave = sin(u.time * 100.0f) * 0.5f + 0.5f; + colour *= 1.0f - u.flicker * 0.04f * flicker_wave; + } + + return float4(colour, 1.0f); +} +)"; +// NOLINTEND(readability-identifier-naming) + +#endif // __APPLE__ + +namespace Rendering { + + // --------------------------------------------------------------------------- + // Destructor + // --------------------------------------------------------------------------- + SDL3GPUShader::~SDL3GPUShader() { + destroy(); + } + + // --------------------------------------------------------------------------- + // init + // --------------------------------------------------------------------------- + auto SDL3GPUShader::init(SDL_Window* window, + SDL_Texture* texture, + const std::string& /*vertex_source*/, + const std::string& /*fragment_source*/) -> bool { + // Si ya estaba inicializado (p.ej. al cambiar borde), liberar recursos + // de textura/pipeline pero mantener el device vivo para evitar conflictos + // con SDL_Renderer en Windows/Vulkan. + if (is_initialized_) { + cleanup(); + } + + window_ = window; + + // Dimensions from the SDL_Texture placeholder + float fw = 0.0F; + float fh = 0.0F; + SDL_GetTextureSize(texture, &fw, &fh); + game_width_ = static_cast(fw); + game_height_ = static_cast(fh); + tex_width_ = game_width_ * oversample_; + tex_height_ = game_height_ * oversample_; + uniforms_.screen_height = static_cast(tex_height_); // Altura de la textura GPU + uniforms_.oversample = static_cast(oversample_); + + // ---------------------------------------------------------------- + // 1. Create GPU device (solo si no existe ya) + // ---------------------------------------------------------------- + if (device_ == nullptr) { +#ifdef __APPLE__ + const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB; +#else + const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_SPIRV; +#endif + device_ = SDL_CreateGPUDevice(PREFERRED, false, nullptr); + if (device_ == nullptr) { + SDL_Log("SDL3GPUShader: SDL_CreateGPUDevice failed: %s", SDL_GetError()); + return false; + } + SDL_Log("SDL3GPUShader: driver = %s", SDL_GetGPUDeviceDriver(device_)); + + // ---------------------------------------------------------------- + // 2. Claim window (una sola vez — no liberar hasta destroy()) + // ---------------------------------------------------------------- + if (!SDL_ClaimWindowForGPUDevice(device_, window_)) { + SDL_Log("SDL3GPUShader: SDL_ClaimWindowForGPUDevice failed: %s", SDL_GetError()); + SDL_DestroyGPUDevice(device_); + device_ = nullptr; + return false; + } + SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, vsync_ ? SDL_GPU_PRESENTMODE_VSYNC : SDL_GPU_PRESENTMODE_IMMEDIATE); + } + + // ---------------------------------------------------------------- + // 3. Create scene texture (upload target + sampler source) + // Format: B8G8R8A8_UNORM matches SDL ARGB8888 byte layout on LE + // ---------------------------------------------------------------- + SDL_GPUTextureCreateInfo tex_info = {}; + tex_info.type = SDL_GPU_TEXTURETYPE_2D; + tex_info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; + tex_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; + tex_info.width = static_cast(tex_width_); + tex_info.height = static_cast(tex_height_); + tex_info.layer_count_or_depth = 1; + tex_info.num_levels = 1; + scene_texture_ = SDL_CreateGPUTexture(device_, &tex_info); + if (scene_texture_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create scene texture: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 4. Create upload transfer buffer (CPU → GPU, size = w*h*4 bytes) + // ---------------------------------------------------------------- + SDL_GPUTransferBufferCreateInfo tb_info = {}; + tb_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + tb_info.size = static_cast(tex_width_ * tex_height_ * 4); + upload_buffer_ = SDL_CreateGPUTransferBuffer(device_, &tb_info); + if (upload_buffer_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create upload buffer: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 5. Create samplers: NEAREST (pixel art) + LINEAR (supersampling) + // ---------------------------------------------------------------- + SDL_GPUSamplerCreateInfo samp_info = {}; + samp_info.min_filter = SDL_GPU_FILTER_NEAREST; + samp_info.mag_filter = SDL_GPU_FILTER_NEAREST; + samp_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST; + samp_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samp_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samp_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + sampler_ = SDL_CreateGPUSampler(device_, &samp_info); + if (sampler_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create sampler: %s", SDL_GetError()); + cleanup(); + return false; + } + + SDL_GPUSamplerCreateInfo lsamp_info = {}; + lsamp_info.min_filter = SDL_GPU_FILTER_LINEAR; + lsamp_info.mag_filter = SDL_GPU_FILTER_LINEAR; + lsamp_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST; + lsamp_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + lsamp_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + lsamp_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + linear_sampler_ = SDL_CreateGPUSampler(device_, &lsamp_info); + if (linear_sampler_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create linear sampler: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 6. Create PostFX graphics pipeline + // ---------------------------------------------------------------- + if (!createPipeline()) { + cleanup(); + return false; + } + + is_initialized_ = true; + SDL_Log("SDL3GPUShader: initialized OK (%dx%d)", tex_width_, tex_height_); + return true; + } + + // --------------------------------------------------------------------------- + // createPipeline + // --------------------------------------------------------------------------- + auto SDL3GPUShader::createPipeline() -> bool { + const SDL_GPUTextureFormat SWAPCHAIN_FMT = SDL_GetGPUSwapchainTextureFormat(device_, window_); + +#ifdef __APPLE__ + SDL_GPUShader* vert = createShaderMSL(device_, POSTFX_VERT_MSL, "postfx_vs", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0); + SDL_GPUShader* frag = createShaderMSL(device_, POSTFX_FRAG_MSL, "postfx_fs", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1); +#else + SDL_GPUShader* vert = createShaderSPIRV(device_, kpostfx_vert_spv, kpostfx_vert_spv_size, "main", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0); + SDL_GPUShader* frag = createShaderSPIRV(device_, kpostfx_frag_spv, kpostfx_frag_spv_size, "main", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1); +#endif + + if ((vert == nullptr) || (frag == nullptr)) { + SDL_Log("SDL3GPUShader: failed to compile PostFX shaders"); + if (vert != nullptr) { SDL_ReleaseGPUShader(device_, vert); } + if (frag != nullptr) { SDL_ReleaseGPUShader(device_, frag); } + return false; + } + + SDL_GPUColorTargetBlendState no_blend = {}; + no_blend.enable_blend = false; + no_blend.enable_color_write_mask = false; + + SDL_GPUColorTargetDescription color_target = {}; + color_target.format = SWAPCHAIN_FMT; + color_target.blend_state = no_blend; + + SDL_GPUVertexInputState no_input = {}; + + SDL_GPUGraphicsPipelineCreateInfo pipe_info = {}; + pipe_info.vertex_shader = vert; + pipe_info.fragment_shader = frag; + pipe_info.vertex_input_state = no_input; + pipe_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + pipe_info.target_info.num_color_targets = 1; + pipe_info.target_info.color_target_descriptions = &color_target; + + pipeline_ = SDL_CreateGPUGraphicsPipeline(device_, &pipe_info); + + SDL_ReleaseGPUShader(device_, vert); + SDL_ReleaseGPUShader(device_, frag); + + if (pipeline_ == nullptr) { + SDL_Log("SDL3GPUShader: pipeline creation failed: %s", SDL_GetError()); + return false; + } + return true; + } + + // --------------------------------------------------------------------------- + // uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer. + // Con supersampling (oversample_ > 1) expande cada pixel del juego a un bloque + // oversample × oversample y hornea la scanline oscura en la última fila del bloque. + // --------------------------------------------------------------------------- + void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) { + if (!is_initialized_ || (upload_buffer_ == nullptr)) { return; } + + void* mapped = SDL_MapGPUTransferBuffer(device_, upload_buffer_, false); + if (mapped == nullptr) { + SDL_Log("SDL3GPUShader: SDL_MapGPUTransferBuffer failed: %s", SDL_GetError()); + return; + } + + if (oversample_ <= 1) { + // Path sin supersampling: copia directa + std::memcpy(mapped, pixels, static_cast(width * height * 4)); + } else { + // Path con supersampling: expande cada pixel a OS×OS, oscurece última fila. + // Replica la fórmula del shader: mix(3.5, 0.42, scanline_strength). + auto* out = static_cast(mapped); + const int OS = oversample_; + const float BRIGHT_MUL = 1.0F + (baked_scanline_strength_ * 2.5F); // rows 0..OS-2 + const float DARK_MUL = 1.0F - (baked_scanline_strength_ * 0.58F); // row OS-1 + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const Uint32 SRC = pixels[(y * width) + x]; + const Uint32 ALPHA = (SRC >> 24) & 0xFFU; + const auto FR = static_cast((SRC >> 16) & 0xFFU); + const auto FG = static_cast((SRC >> 8) & 0xFFU); + const auto FB = static_cast(SRC & 0xFFU); + + auto make_px = [ALPHA](float rv, float gv, float bv) -> Uint32 { + auto cl = [](float v) -> Uint32 { return static_cast(std::min(255.0F, v)); }; + return (ALPHA << 24) | (cl(rv) << 16) | (cl(gv) << 8) | cl(bv); + }; + + const Uint32 BRIGHT = make_px(FR * BRIGHT_MUL, FG * BRIGHT_MUL, FB * BRIGHT_MUL); + const Uint32 DARK = make_px(FR * DARK_MUL, FG * DARK_MUL, FB * DARK_MUL); + + for (int dy = 0; dy < OS; ++dy) { + const Uint32 OUT_PX = (dy == OS - 1) ? DARK : BRIGHT; + const int DST_Y = (y * OS) + dy; + for (int dx = 0; dx < OS; ++dx) { + out[(DST_Y * (width * OS)) + ((x * OS) + dx)] = OUT_PX; + } + } + } + } + } + + SDL_UnmapGPUTransferBuffer(device_, upload_buffer_); + } + + // --------------------------------------------------------------------------- + // render — upload scene texture + PostFX pass → swapchain + // --------------------------------------------------------------------------- + void SDL3GPUShader::render() { + if (!is_initialized_) { return; } + + SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_); + if (cmd == nullptr) { + SDL_Log("SDL3GPUShader: SDL_AcquireGPUCommandBuffer failed: %s", SDL_GetError()); + return; + } + + // ---- Copy pass: transfer buffer → scene texture ---- + SDL_GPUCopyPass* copy = SDL_BeginGPUCopyPass(cmd); + if (copy != nullptr) { + SDL_GPUTextureTransferInfo src = {}; + src.transfer_buffer = upload_buffer_; + src.offset = 0; + src.pixels_per_row = static_cast(tex_width_); + src.rows_per_layer = static_cast(tex_height_); + + SDL_GPUTextureRegion dst = {}; + dst.texture = scene_texture_; + dst.w = static_cast(tex_width_); + dst.h = static_cast(tex_height_); + dst.d = 1; + + SDL_UploadToGPUTexture(copy, &src, &dst, false); + SDL_EndGPUCopyPass(copy); + } + + // ---- Acquire swapchain texture ---- + SDL_GPUTexture* swapchain = nullptr; + Uint32 sw = 0; + Uint32 sh = 0; + if (!SDL_AcquireGPUSwapchainTexture(cmd, window_, &swapchain, &sw, &sh)) { + SDL_Log("SDL3GPUShader: SDL_AcquireGPUSwapchainTexture failed: %s", SDL_GetError()); + SDL_SubmitGPUCommandBuffer(cmd); + return; + } + if (swapchain == nullptr) { + // Window minimized — skip frame + SDL_SubmitGPUCommandBuffer(cmd); + return; + } + + // ---- Render pass: PostFX → swapchain ---- + SDL_GPUColorTargetInfo color_target = {}; + color_target.texture = swapchain; + color_target.load_op = SDL_GPU_LOADOP_CLEAR; + color_target.store_op = SDL_GPU_STOREOP_STORE; + color_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F}; + + SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, nullptr); + if (pass != nullptr) { + SDL_BindGPUGraphicsPipeline(pass, pipeline_); + + // Calcular viewport usando las dimensiones lógicas del canvas (game_width_/height_), + // no las de la textura GPU (que pueden ser game×3 con supersampling). + // El GPU escala la textura para cubrir el viewport independientemente de su resolución. + float vx = 0.0F; + float vy = 0.0F; + float vw = 0.0F; + float vh = 0.0F; + if (integer_scale_) { + const int SCALE = std::max(1, std::min(static_cast(sw) / game_width_, static_cast(sh) / game_height_)); + vw = static_cast(game_width_ * SCALE); + vh = static_cast(game_height_ * SCALE); + } else { + const float SCALE = std::min( + static_cast(sw) / static_cast(game_width_), + static_cast(sh) / static_cast(game_height_)); + vw = static_cast(game_width_) * SCALE; + vh = static_cast(game_height_) * SCALE; + } + vx = std::floor((static_cast(sw) - vw) * 0.5F); + vy = std::floor((static_cast(sh) - vh) * 0.5F); + SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F}; + SDL_SetGPUViewport(pass, &vp); + + // pixel_scale: pixels físicos por pixel lógico de juego (para scanlines sin SS). + // Con SS las scanlines están horneadas en CPU → scanline_strength=0 → no se usa. + uniforms_.pixel_scale = (game_height_ > 0) + ? (vh / static_cast(game_height_)) + : 1.0F; + uniforms_.time = static_cast(SDL_GetTicks()) / 1000.0F; + uniforms_.oversample = static_cast(oversample_); + + // Con supersampling usamos LINEAR para que el escalado a zooms no-múltiplo-de-3 + // promedia correctamente las filas de scanline horneadas en CPU. + SDL_GPUSampler* active_sampler = (oversample_ > 1 && linear_sampler_ != nullptr) + ? linear_sampler_ + : sampler_; + + SDL_GPUTextureSamplerBinding binding = {}; + binding.texture = scene_texture_; + binding.sampler = active_sampler; + SDL_BindGPUFragmentSamplers(pass, 0, &binding, 1); + + SDL_PushGPUFragmentUniformData(cmd, 0, &uniforms_, sizeof(PostFXUniforms)); + + SDL_DrawGPUPrimitives(pass, 3, 1, 0, 0); + SDL_EndGPURenderPass(pass); + } + + SDL_SubmitGPUCommandBuffer(cmd); + } + + // --------------------------------------------------------------------------- + // cleanup — libera pipeline/texturas/buffer pero mantiene device + swapchain + // --------------------------------------------------------------------------- + void SDL3GPUShader::cleanup() { + is_initialized_ = false; + + if (device_ != nullptr) { + SDL_WaitForGPUIdle(device_); + + if (pipeline_ != nullptr) { + SDL_ReleaseGPUGraphicsPipeline(device_, pipeline_); + pipeline_ = nullptr; + } + if (scene_texture_ != nullptr) { + SDL_ReleaseGPUTexture(device_, scene_texture_); + scene_texture_ = nullptr; + } + if (upload_buffer_ != nullptr) { + SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); + upload_buffer_ = nullptr; + } + if (sampler_ != nullptr) { + SDL_ReleaseGPUSampler(device_, sampler_); + sampler_ = nullptr; + } + if (linear_sampler_ != nullptr) { + SDL_ReleaseGPUSampler(device_, linear_sampler_); + linear_sampler_ = nullptr; + } + // device_ y el claim de la ventana se mantienen vivos + } + } + + // --------------------------------------------------------------------------- + // destroy — limpieza completa incluyendo device y swapchain (solo al cerrar) + // --------------------------------------------------------------------------- + void SDL3GPUShader::destroy() { + cleanup(); + + if (device_ != nullptr) { + if (window_ != nullptr) { + SDL_ReleaseWindowFromGPUDevice(device_, window_); + } + SDL_DestroyGPUDevice(device_); + device_ = nullptr; + } + window_ = nullptr; + } + + // --------------------------------------------------------------------------- + // Shader creation helpers + // --------------------------------------------------------------------------- + auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device, + const char* msl_source, + const char* entrypoint, + SDL_GPUShaderStage stage, + Uint32 num_samplers, + Uint32 num_uniform_buffers) -> SDL_GPUShader* { + SDL_GPUShaderCreateInfo info = {}; + info.code = reinterpret_cast(msl_source); + info.code_size = std::strlen(msl_source) + 1; + info.entrypoint = entrypoint; + info.format = SDL_GPU_SHADERFORMAT_MSL; + info.stage = stage; + info.num_samplers = num_samplers; + info.num_uniform_buffers = num_uniform_buffers; + SDL_GPUShader* shader = SDL_CreateGPUShader(device, &info); + if (shader == nullptr) { + SDL_Log("SDL3GPUShader: MSL shader '%s' failed: %s", entrypoint, SDL_GetError()); + } + return shader; + } + + auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device, // NOLINT(readability-convert-member-functions-to-static) + const uint8_t* spv_code, + size_t spv_size, + const char* entrypoint, + SDL_GPUShaderStage stage, + Uint32 num_samplers, + Uint32 num_uniform_buffers) -> SDL_GPUShader* { + SDL_GPUShaderCreateInfo info = {}; + info.code = spv_code; + info.code_size = spv_size; + info.entrypoint = entrypoint; + info.format = SDL_GPU_SHADERFORMAT_SPIRV; + info.stage = stage; + info.num_samplers = num_samplers; + info.num_uniform_buffers = num_uniform_buffers; + SDL_GPUShader* shader = SDL_CreateGPUShader(device, &info); + if (shader == nullptr) { + SDL_Log("SDL3GPUShader: SPIRV shader '%s' failed: %s", entrypoint, SDL_GetError()); + } + return shader; + } + + void SDL3GPUShader::setPostFXParams(const PostFXParams& p) { + uniforms_.vignette_strength = p.vignette; + uniforms_.chroma_strength = p.chroma; + uniforms_.mask_strength = p.mask; + uniforms_.gamma_strength = p.gamma; + uniforms_.curvature = p.curvature; + uniforms_.bleeding = p.bleeding; + uniforms_.flicker = p.flicker; + + // Con supersampling las scanlines se hornean en CPU (uploadPixels). + // El shader recibe strength=0 para no aplicarlas de nuevo en GPU. + baked_scanline_strength_ = p.scanlines; + uniforms_.scanline_strength = (oversample_ > 1) ? 0.0F : p.scanlines; + } + + void SDL3GPUShader::setVSync(bool vsync) { + vsync_ = vsync; + if (device_ != nullptr && window_ != nullptr) { + SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, vsync_ ? SDL_GPU_PRESENTMODE_VSYNC : SDL_GPU_PRESENTMODE_IMMEDIATE); + } + } + + void SDL3GPUShader::setScaleMode(bool integer_scale) { + integer_scale_ = integer_scale; + } + + // --------------------------------------------------------------------------- + // setOversample — cambia el factor SS; recrea texturas si ya está inicializado + // --------------------------------------------------------------------------- + void SDL3GPUShader::setOversample(int factor) { + const int NEW_FACTOR = std::max(1, factor); + if (NEW_FACTOR == oversample_) { return; } + oversample_ = NEW_FACTOR; + if (is_initialized_) { + reinitTexturesAndBuffer(); + // scanline_strength se actualizará en el próximo setPostFXParams + } + } + + // --------------------------------------------------------------------------- + // reinitTexturesAndBuffer — recrea scene_texture_ y upload_buffer_ con el + // tamaño actual (game × oversample_). No toca pipeline ni samplers. + // --------------------------------------------------------------------------- + auto SDL3GPUShader::reinitTexturesAndBuffer() -> bool { + if (device_ == nullptr) { return false; } + SDL_WaitForGPUIdle(device_); + + if (scene_texture_ != nullptr) { + SDL_ReleaseGPUTexture(device_, scene_texture_); + scene_texture_ = nullptr; + } + if (upload_buffer_ != nullptr) { + SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); + upload_buffer_ = nullptr; + } + + tex_width_ = game_width_ * oversample_; + tex_height_ = game_height_ * oversample_; + uniforms_.screen_height = static_cast(tex_height_); + uniforms_.oversample = static_cast(oversample_); + + SDL_GPUTextureCreateInfo tex_info = {}; + tex_info.type = SDL_GPU_TEXTURETYPE_2D; + tex_info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; + tex_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; + tex_info.width = static_cast(tex_width_); + tex_info.height = static_cast(tex_height_); + tex_info.layer_count_or_depth = 1; + tex_info.num_levels = 1; + scene_texture_ = SDL_CreateGPUTexture(device_, &tex_info); + if (scene_texture_ == nullptr) { + SDL_Log("SDL3GPUShader: reinit — failed to create scene texture: %s", SDL_GetError()); + return false; + } + + SDL_GPUTransferBufferCreateInfo tb_info = {}; + tb_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + tb_info.size = static_cast(tex_width_ * tex_height_ * 4); + upload_buffer_ = SDL_CreateGPUTransferBuffer(device_, &tb_info); + if (upload_buffer_ == nullptr) { + SDL_Log("SDL3GPUShader: reinit — failed to create upload buffer: %s", SDL_GetError()); + SDL_ReleaseGPUTexture(device_, scene_texture_); + scene_texture_ = nullptr; + return false; + } + + SDL_Log("SDL3GPUShader: oversample %d → texture %dx%d", oversample_, tex_width_, tex_height_); + return true; + } + +} // namespace Rendering diff --git a/source/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/rendering/sdl3gpu/sdl3gpu_shader.hpp new file mode 100644 index 0000000..1fcef3c --- /dev/null +++ b/source/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include +#include + +#include "rendering/shader_backend.hpp" + +// PostFX uniforms pushed to fragment stage each frame. +// Must match the MSL struct and GLSL uniform block layout. +// 12 floats = 48 bytes — meets Metal/Vulkan 16-byte alignment requirement. +struct PostFXUniforms { + float vignette_strength; // 0 = none, ~0.8 = subtle + float chroma_strength; // 0 = off, ~0.2 = subtle chromatic aberration + float scanline_strength; // 0 = off, 1 = full + float screen_height; // logical height in pixels (used by bleeding effect) + float mask_strength; // 0 = off, 1 = full phosphor dot mask + float gamma_strength; // 0 = off, 1 = full gamma 2.4/2.2 correction + float curvature; // 0 = flat, 1 = max barrel distortion + float bleeding; // 0 = off, 1 = max NTSC chrominance bleeding + float pixel_scale; // physical pixels per logical pixel (vh / tex_height_) + float time; // seconds since SDL init (SDL_GetTicks() / 1000.0f) + float oversample; // supersampling factor (1.0 = off, 3.0 = 3×SS) + float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — keep struct at 48 bytes (3 × 16) +}; + +namespace Rendering { + + /** + * @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux) + * + * Reemplaza el backend OpenGL para que los shaders PostFX funcionen en macOS. + * Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene) + * → PostFX render pass → swapchain → present + */ + class SDL3GPUShader : public ShaderBackend { + public: + SDL3GPUShader() = default; + ~SDL3GPUShader() override; + + auto init(SDL_Window* window, + SDL_Texture* texture, + const std::string& vertex_source, + const std::string& fragment_source) -> bool override; + + void render() override; + void setTextureSize(float width, float height) override {} + void cleanup() final; // Libera pipeline/texturas pero mantiene el device vivo + void destroy(); // Limpieza completa (device + swapchain); llamar solo al cerrar + [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } + + // Sube píxeles ARGB8888 desde CPU; llamado antes de render() + void uploadPixels(const Uint32* pixels, int width, int height) override; + + // Actualiza los parámetros de intensidad de los efectos PostFX + void setPostFXParams(const PostFXParams& p) override; + + // Activa/desactiva VSync en el swapchain + void setVSync(bool vsync) override; + + // Activa/desactiva escalado entero (integer scale) + void setScaleMode(bool integer_scale) override; + + // Establece factor de supersampling (1 = off, 3 = 3×SS) + void setOversample(int factor) override; + + private: + static auto createShaderMSL(SDL_GPUDevice* device, + const char* msl_source, + const char* entrypoint, + SDL_GPUShaderStage stage, + Uint32 num_samplers, + Uint32 num_uniform_buffers) -> SDL_GPUShader*; + + static auto createShaderSPIRV(SDL_GPUDevice* device, + const uint8_t* spv_code, + size_t spv_size, + const char* entrypoint, + SDL_GPUShaderStage stage, + Uint32 num_samplers, + Uint32 num_uniform_buffers) -> SDL_GPUShader*; + + auto createPipeline() -> bool; + auto reinitTexturesAndBuffer() -> bool; // Recrea textura y buffer con oversample actual + + SDL_Window* window_ = nullptr; + SDL_GPUDevice* device_ = nullptr; + SDL_GPUGraphicsPipeline* pipeline_ = nullptr; + SDL_GPUTexture* scene_texture_ = nullptr; + SDL_GPUTransferBuffer* upload_buffer_ = nullptr; + SDL_GPUSampler* sampler_ = nullptr; // NEAREST — para path sin supersampling + SDL_GPUSampler* linear_sampler_ = nullptr; // LINEAR — para path con supersampling + + PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F}; + + int game_width_ = 0; // Dimensiones originales del canvas (sin SS) + int game_height_ = 0; + int tex_width_ = 0; // Dimensiones de la textura GPU (game × oversample_) + int tex_height_ = 0; + int oversample_ = 1; // Factor SS actual (1 o 3) + float baked_scanline_strength_ = 0.0F; // Guardado para hornear en CPU + bool is_initialized_ = false; + bool vsync_ = true; + bool integer_scale_ = false; + }; + +} // namespace Rendering diff --git a/source/rendering/shader_backend.hpp b/source/rendering/shader_backend.hpp index 9fe1774..8f99b6e 100644 --- a/source/rendering/shader_backend.hpp +++ b/source/rendering/shader_backend.hpp @@ -6,6 +6,20 @@ namespace Rendering { + /** + * @brief Parámetros de intensidad de los efectos PostFX + */ + struct PostFXParams { + float vignette = 0.0F; + float scanlines = 0.0F; + float chroma = 0.0F; + float mask = 0.0F; + float gamma = 0.0F; + float curvature = 0.0F; + float bleeding = 0.0F; + float flicker = 0.0F; + }; + /** * @brief Interfaz abstracta para backends de renderizado con shaders * @@ -51,6 +65,12 @@ namespace Rendering { * @return true si usa aceleración (OpenGL/Metal/Vulkan) */ [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0; + + virtual void uploadPixels(const Uint32* /*pixels*/, int /*width*/, int /*height*/) {} + virtual void setPostFXParams(const PostFXParams& /*p*/) {} + virtual void setVSync(bool /*vsync*/) {} + virtual void setScaleMode(bool /*integer_scale*/) {} + virtual void setOversample(int /*factor*/) {} }; } // namespace Rendering diff --git a/source/screen.cpp b/source/screen.cpp index 1610147..9072f01 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -1,8 +1,9 @@ #include "screen.hpp" -#include // Para SDL_SetRenderTarget, SDL_RenderTexture, SDL_SetRenderDrawColor, SDL_SetRenderVSync, SDL_LogCategory, SDL_GetError, SDL_LogError, SDL_LogInfo, SDL_RendererLogicalPresentation, SDL_SetRenderLogicalPresentation, SDL_CreateTexture, SDL_DestroyTexture, SDL_DestroyWindow, SDL_GetDisplayName, SDL_GetTicks, SDL_Quit, SDL_RENDERER_VSYNC_DISABLED, SDL_RenderClear, SDL_CreateRenderer, SDL_CreateWindow, SDL_DestroyRenderer, SDL_DisplayID, SDL_FRect, SDL_GetCurrentDisplayMode, SDL_GetDisplays, SDL_GetRenderTarget, SDL_GetWindowPosition, SDL_GetWindowSize, SDL_Init, SDL_LogWarn, SDL_PixelFormat, SDL_RenderFillRect, SDL_RenderPresent, SDL_SetHint, SDL_SetRenderDrawBlendMode, SDL_SetTextureScaleMode, SDL_SetWindowFullscreen, SDL_SetWindowPosition, SDL_SetWindowSize, SDL_TextureAccess, SDL_free, SDL_BLENDMODE_BLEND, SDL_HINT_RENDER_DRIVER, SDL_INIT_VIDEO, SDL_ScaleMode, SDL_WINDOW_FULLSCREEN, SDL_WINDOW_OPENGL, SDL_WindowFlags +#include // Para SDL_SetRenderTarget, SDL_RenderTexture, SDL_SetRenderDrawColor, SDL_SetRenderVSync, SDL_LogCategory, SDL_GetError, SDL_LogError, SDL_LogInfo, SDL_RendererLogicalPresentation, SDL_SetRenderLogicalPresentation, SDL_CreateTexture, SDL_DestroyTexture, SDL_DestroyWindow, SDL_GetDisplayName, SDL_GetTicks, SDL_Quit, SDL_RENDERER_VSYNC_DISABLED, SDL_RenderClear, SDL_CreateRenderer, SDL_CreateWindow, SDL_DestroyRenderer, SDL_DisplayID, SDL_FRect, SDL_GetCurrentDisplayMode, SDL_GetDisplays, SDL_GetRenderTarget, SDL_GetWindowPosition, SDL_GetWindowSize, SDL_Init, SDL_LogWarn, SDL_PixelFormat, SDL_RenderFillRect, SDL_RenderPresent, SDL_SetHint, SDL_SetRenderDrawBlendMode, SDL_SetTextureScaleMode, SDL_SetWindowFullscreen, SDL_SetWindowPosition, SDL_SetWindowSize, SDL_TextureAccess, SDL_free, SDL_BLENDMODE_BLEND, SDL_HINT_RENDER_DRIVER, SDL_INIT_VIDEO, SDL_ScaleMode, SDL_WINDOW_FULLSCREEN, SDL_WindowFlags #include // Para min, max +#include // Para memcpy #include // Para allocator, shared_ptr, unique_ptr, __shared_ptr_access, make_shared, make_unique #include // Para basic_string, operator+, char_traits, to_string, string #include // Para vector @@ -11,8 +12,7 @@ #include "mouse.hpp" // Para updateCursorVisibility #include "options.hpp" // Para Video, video, Window, window #include "param.hpp" // Para Param, param, ParamGame, ParamDebug -#include "rendering/opengl/opengl_shader.hpp" // Para OpenGLShader -#include "shader_backend.hpp" // Para ShaderBackend +#include "rendering/sdl3gpu/sdl3gpu_shader.hpp" // Para SDL3GPUShader #include "text.hpp" // Para Text #include "texture.hpp" // Para Texture #include "ui/logger.hpp" // Para info @@ -23,7 +23,10 @@ Screen* Screen::instance = nullptr; // Inicializa la instancia única del singleton -void Screen::init() { Screen::instance = new Screen(); } +void Screen::init() { + Screen::instance = new Screen(); + Screen::initShaders(); // Llamar aquí para que Screen::get() ya devuelva la instancia +} // Libera la instancia void Screen::destroy() { delete Screen::instance; } @@ -44,9 +47,12 @@ Screen::Screen() initSDLVideo(); // Crea la textura de destino - game_canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); + game_canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); SDL_SetTextureScaleMode(game_canvas_, SDL_SCALEMODE_NEAREST); + // Inicializar buffer de píxeles para SDL3GPU + pixel_buffer_.resize(static_cast(param.game.width) * static_cast(param.game.height)); + // Crea el objeto de texto createText(); @@ -63,8 +69,6 @@ Screen::Screen() SDL_RenderClear(renderer_); SDL_RenderPresent(renderer_); - // Ahora sí inicializar los shaders - initShaders(); } // Destructor @@ -101,15 +105,37 @@ void Screen::coreRender() { // Renderiza el contenido del game_canvas_ void Screen::renderPresent() { +#ifndef NO_SHADERS + if (shader_backend_ && shader_backend_->isHardwareAccelerated()) { + // Leer píxeles de game_canvas_ con la API SDL3 (devuelve SDL_Surface*) + SDL_SetRenderTarget(renderer_, game_canvas_); + SDL_Surface* surface = SDL_RenderReadPixels(renderer_, nullptr); + if (surface != nullptr) { + if (surface->format == SDL_PIXELFORMAT_ARGB8888) { + std::memcpy(pixel_buffer_.data(), surface->pixels, + pixel_buffer_.size() * sizeof(Uint32)); + } else { + SDL_Surface* converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888); + if (converted != nullptr) { + std::memcpy(pixel_buffer_.data(), converted->pixels, + pixel_buffer_.size() * sizeof(Uint32)); + SDL_DestroySurface(converted); + } + } + SDL_DestroySurface(surface); + } + SDL_SetRenderTarget(renderer_, nullptr); + // Subir a GPU y presentar con PostFX + shader_backend_->uploadPixels(pixel_buffer_.data(), param.game.width, param.game.height); + shader_backend_->render(); + return; + } +#endif + // Fallback: SDL_Renderer SDL_SetRenderTarget(renderer_, nullptr); clean(); - - if (Options::video.shaders && shader_backend_) { - shader_backend_->render(); - } else { - SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr); - SDL_RenderPresent(renderer_); - } + SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr); + SDL_RenderPresent(renderer_); } // Establece el modo de video @@ -230,61 +256,32 @@ void Screen::renderInfo() const { } } #endif -// Carga el contenido de los archivos GLSL -void Screen::loadShaders() { - if (vertex_shader_source_.empty()) { - // Detectar si necesitamos OpenGL ES (Raspberry Pi) - // Intentar cargar versión ES primero si existe - std::string vertex_file = "crtpi_vertex_es.glsl"; - auto data = Asset::get()->loadData(vertex_file); - - if (data.empty()) { - // Si no existe versión ES, usar versión Desktop - vertex_file = "crtpi_vertex.glsl"; - data = Asset::get()->loadData(vertex_file); - // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Usando shaders OpenGL Desktop 3.3"); - Logger::info("Usando shaders OpenGL Desktop 3.3"); - } else { - // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Usando shaders OpenGL ES 3.0 (Raspberry Pi)"); - Logger::info("Usando shaders OpenGL ES 3.0 (Raspberry Pi)"); - } - - if (!data.empty()) { - vertex_shader_source_ = std::string(data.begin(), data.end()); - } +// Inicializa los shaders (SDL3GPU) +void Screen::initShaders() { +#ifndef NO_SHADERS + auto* self = Screen::get(); + if (self == nullptr) { + SDL_Log("Screen::initShaders: instance is null, skipping"); + return; } - if (fragment_shader_source_.empty()) { - // Intentar cargar versión ES primero si existe - std::string fragment_file = "crtpi_fragment_es.glsl"; - auto data = Asset::get()->loadData(fragment_file); - - if (data.empty()) { - // Si no existe versión ES, usar versión Desktop - fragment_file = "crtpi_fragment.glsl"; - data = Asset::get()->loadData(fragment_file); - } - - if (!data.empty()) { - fragment_shader_source_ = std::string(data.begin(), data.end()); - } + if (!self->shader_backend_) { + self->shader_backend_ = std::make_unique(); } + if (!self->shader_backend_->isHardwareAccelerated()) { + const bool ok = self->shader_backend_->init(self->window_, self->game_canvas_, "", ""); + SDL_Log("Screen::initShaders: SDL3GPUShader::init() = %s", ok ? "OK" : "FAILED"); + } + SDL_Log("Screen::initShaders: presets=%d current=%d postfx=%s", + static_cast(Options::postfx_presets.size()), + Options::current_postfx_preset, + Options::video.postfx ? "ON" : "OFF"); + self->applyCurrentPostFXPreset(); +#endif } -// Inicializa los shaders -void Screen::initShaders() { -#ifndef __APPLE__ - if (Options::video.shaders) { - loadShaders(); - if (!shader_backend_) { - shader_backend_ = std::make_unique(); - } - shader_backend_->init(window_, game_canvas_, vertex_shader_source_, fragment_shader_source_); - } -#else - // En macOS, OpenGL está deprecated y rinde mal - // TODO: Implementar backend de Metal para shaders en macOS - Logger::info("WARNING: Shaders no disponibles en macOS (OpenGL deprecated). Usa Metal backend.", Logger::YELLOW); -#endif +// Inicializa PostFX (alias de initShaders) +void Screen::initPostFX() { + initShaders(); } // Calcula el tamaño de la ventana @@ -350,32 +347,13 @@ auto Screen::initSDLVideo() -> bool { SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Failed to set Metal hint!"); } -#else - // Configurar hint de render driver - if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Warning: Failed to set OpenGL hint!"); - } - -#ifdef _WIN32 - // Windows: Pedir explícitamente OpenGL 3.3 Core Profile - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Solicitando OpenGL 3.3 Core Profile"); - Logger::info("Solicitando OpenGL 3.3 Core Profile"); -#else - // Linux: Dejar que SDL elija (Desktop 3.3 en PC, ES 3.0 en RPi automáticamente) - // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Usando OpenGL por defecto del sistema"); - Logger::info("Usando OpenGL por defecto del sistema"); -#endif #endif // Crear ventana #ifdef __APPLE__ SDL_WindowFlags window_flags = SDL_WINDOW_METAL; #else - SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL; + SDL_WindowFlags window_flags = 0; #endif if (Options::video.fullscreen) { window_flags |= SDL_WINDOW_FULLSCREEN; @@ -465,22 +443,79 @@ void Screen::getDisplayInfo() { } } -// Alterna entre activar y desactivar los shaders +// Alterna entre activar y desactivar los shaders (backward compat) void Screen::toggleShaders() { - Options::video.shaders = !Options::video.shaders; - initShaders(); + Screen::togglePostFX(); +} + +// Alterna entre activar y desactivar los efectos PostFX +void Screen::togglePostFX() { + Options::video.postfx = !Options::video.postfx; + auto* self = Screen::get(); + if (self != nullptr) { + self->applyCurrentPostFXPreset(); + } +} + +// Avanza al siguiente preset PostFX +void Screen::nextPostFXPreset() { + if (Options::postfx_presets.empty()) { return; } + Options::current_postfx_preset = (Options::current_postfx_preset + 1) % static_cast(Options::postfx_presets.size()); + auto* self = Screen::get(); + if (self != nullptr) { + self->applyCurrentPostFXPreset(); + } +} + +// Alterna entre activar y desactivar el supersampling 3x +void Screen::toggleSupersampling() { + Options::video.supersampling = !Options::video.supersampling; + auto* self = Screen::get(); + if (self != nullptr && self->shader_backend_) { + self->shader_backend_->setOversample(Options::video.supersampling ? 3 : 1); + } +} + +// Aplica el preset PostFX activo al backend +void Screen::applyCurrentPostFXPreset() { + if (!shader_backend_) { return; } + Rendering::PostFXParams p{}; + if (Options::video.postfx && !Options::postfx_presets.empty()) { + const auto& preset = Options::postfx_presets.at(static_cast(Options::current_postfx_preset)); + p.vignette = preset.vignette; + p.scanlines = preset.scanlines; + p.chroma = preset.chroma; + p.mask = preset.mask; + p.gamma = preset.gamma; + p.curvature = preset.curvature; + p.bleeding = preset.bleeding; + p.flicker = preset.flicker; + SDL_Log("Screen::applyCurrentPostFXPreset: preset='%s' scan=%.2f vign=%.2f chroma=%.2f", + preset.name.c_str(), p.scanlines, p.vignette, p.chroma); + } else { + SDL_Log("Screen::applyCurrentPostFXPreset: PostFX=%s presets=%d → passthrough", + Options::video.postfx ? "ON" : "OFF", + static_cast(Options::postfx_presets.size())); + } + shader_backend_->setPostFXParams(p); } // Alterna entre activar y desactivar el escalado entero void Screen::toggleIntegerScale() { Options::video.integer_scale = !Options::video.integer_scale; SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX); + if (shader_backend_) { + shader_backend_->setScaleMode(Options::video.integer_scale); + } } // Alterna entre activar y desactivar el V-Sync void Screen::toggleVSync() { Options::video.vsync = !Options::video.vsync; SDL_SetRenderVSync(renderer_, Options::video.vsync ? 1 : SDL_RENDERER_VSYNC_DISABLED); + if (shader_backend_) { + shader_backend_->setVSync(Options::video.vsync); + } } // Establece el estado del V-Sync diff --git a/source/screen.hpp b/source/screen.hpp index 18d9044..bfe5e46 100644 --- a/source/screen.hpp +++ b/source/screen.hpp @@ -4,6 +4,7 @@ #include // Para shared_ptr #include // Para string +#include // Para vector #include "color.hpp" // Para Color #include "options.hpp" // Para VideoOptions, video @@ -40,12 +41,16 @@ class Screen { auto decWindowSize() -> bool; // Reduce el tamaño de la ventana auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana void applySettings(); // Aplica los valores de las opciones - static void initShaders(); // Inicializa los shaders + static void initShaders(); // Inicializa los shaders (SDL3GPU) + static void initPostFX(); // Inicializa PostFX (alias de initShaders) // --- Efectos visuales --- void shake(int desp = 2, float delay_s = 0.05F, float duration_s = 0.133F) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay_s, duration_s); } // Agita la pantalla (tiempo en segundos) void flash(Color color, float duration_s = 0.167F, float delay_s = 0.0F) { flash_effect_ = FlashEffect(true, duration_s, delay_s, color); } // Pone la pantalla de color (tiempo en segundos) - static void toggleShaders(); // Alterna entre activar y desactivar los shaders + static void toggleShaders(); // Alterna entre activar y desactivar los shaders (backward compat) + static void togglePostFX(); // Alterna entre activar y desactivar los efectos PostFX + static void nextPostFXPreset(); // Avanza al siguiente preset PostFX + static void toggleSupersampling(); // Alterna entre activar y desactivar el supersampling 3x void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero void toggleVSync(); // Alterna entre activar y desactivar el V-Sync void setVSync(bool enabled); // Establece el estado del V-Sync @@ -214,14 +219,13 @@ class Screen { ServiceMenu* service_menu_; // Objeto para mostrar el menú de servicio Notifier* notifier_; // Objeto para mostrar las notificaciones por pantalla std::shared_ptr text_; // Objeto para escribir texto en pantalla - std::unique_ptr shader_backend_; // Backend de shaders (OpenGL/Metal/Vulkan) + std::unique_ptr shader_backend_; // Backend de shaders (SDL3GPU) // --- Variables de estado --- - SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego - SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego - std::string vertex_shader_source_; // Almacena el vertex shader - std::string fragment_shader_source_; // Almacena el fragment shader - FPS fps_; // Gestión de frames por segundo + SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego + SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego + std::vector pixel_buffer_; // Buffer de píxeles para SDL_RenderReadPixels + FPS fps_; // Gestión de frames por segundo FlashEffect flash_effect_; // Efecto de flash en pantalla ShakeEffect shake_effect_; // Efecto de agitar la pantalla bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada @@ -231,17 +235,17 @@ class Screen { #endif // --- Métodos internos --- - auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana - void renderFlash(); // Dibuja el efecto de flash en la pantalla - void renderShake(); // Aplica el efecto de agitar la pantalla - void renderInfo() const; // Muestra información por pantalla - void renderPresent(); // Selecciona y ejecuta el método de renderizado adecuado - void loadShaders(); // Carga el contenido del archivo GLSL - void adjustWindowSize(); // Calcula el tamaño de la ventana - void getDisplayInfo(); // Obtiene información sobre la pantalla - void renderOverlays(); // Renderiza todos los overlays y efectos - void renderAttenuate(); // Atenúa la pantalla - void createText(); // Crea el objeto de texto + auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana + void renderFlash(); // Dibuja el efecto de flash en la pantalla + void renderShake(); // Aplica el efecto de agitar la pantalla + void renderInfo() const; // Muestra información por pantalla + void renderPresent(); // Selecciona y ejecuta el método de renderizado adecuado + void applyCurrentPostFXPreset(); // Aplica el preset PostFX activo al backend + void adjustWindowSize(); // Calcula el tamaño de la ventana + void getDisplayInfo(); // Obtiene información sobre la pantalla + void renderOverlays(); // Renderiza todos los overlays y efectos + void renderAttenuate(); // Atenúa la pantalla + void createText(); // Crea el objeto de texto // --- Constructores y destructor privados (singleton) --- Screen(); // Constructor privado diff --git a/tools/shaders/compile_spirv.sh b/tools/shaders/compile_spirv.sh new file mode 100755 index 0000000..e834f1a --- /dev/null +++ b/tools/shaders/compile_spirv.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Compile Vulkan GLSL shaders to SPIR-V and update the C++ headers used by SDL3GPUShader. +# Required: glslc (from Vulkan SDK or: brew install glslang / apt install glslang-tools) +# +# Run from the project root: tools/shaders/compile_spirv.sh + +set -e + +SHADERS_DIR="data/shaders" +HEADERS_DIR="source/rendering/sdl3gpu" + +if ! command -v glslc &> /dev/null; then + echo "ERROR: glslc not found. Install Vulkan SDK or run:" + echo " macOS: brew install glslang" + echo " Linux: sudo apt install glslang-tools" + exit 1 +fi + +echo "Compiling SPIR-V shaders..." + +glslc "${SHADERS_DIR}/postfx.vert" -o /tmp/postfx.vert.spv +glslc "${SHADERS_DIR}/postfx.frag" -o /tmp/postfx.frag.spv + +echo "Generating C++ headers..." + +xxd -i /tmp/postfx.vert.spv | \ + sed 's/unsigned char .*postfx_vert_spv\[\]/static const uint8_t kpostfx_vert_spv[]/' | \ + sed 's/unsigned int .*postfx_vert_spv_len/static const size_t kpostfx_vert_spv_size/' \ + > "${HEADERS_DIR}/postfx_vert_spv.h" + +xxd -i /tmp/postfx.frag.spv | \ + sed 's/unsigned char .*postfx_frag_spv\[\]/static const uint8_t kpostfx_frag_spv[]/' | \ + sed 's/unsigned int .*postfx_frag_spv_len/static const size_t kpostfx_frag_spv_size/' \ + > "${HEADERS_DIR}/postfx_frag_spv.h" + +# Prepend required includes to the headers +for f in "${HEADERS_DIR}/postfx_vert_spv.h" "${HEADERS_DIR}/postfx_frag_spv.h"; do + echo -e "#pragma once\n#include \n#include \n$(cat "$f")" > "$f" +done + +echo "Done. Headers updated in ${HEADERS_DIR}/" +echo " postfx_vert_spv.h" +echo " postfx_frag_spv.h" +echo "Rebuild the project to use the new shaders."