From 777012d7440d34f3bdce47b6188ec9fbd8bd2438 Mon Sep 17 00:00:00 2001 From: Raffaello Bertini Date: Fri, 22 May 2020 11:50:24 +0100 Subject: [PATCH] v0.3.0 (#86) * preparing for v0.3.0 * rebase * add clearLine method. fix #42 * update readme. fix #121 * for loop refactor in a C++ way * refactor _setCharAtCursorPosition name * refactor clearLine * add fill method. Fix #113 * decouple VgaTerminal drawing functionality to Window. Fix #122 * cursor blinking flag. Fix #39 * cursor speed from enum class, partially fix #38 * [cmake] macro to generate example. Fix #126 * update version string to 0.3.0 fixes #129 * build switch for precise timer,fixes #131 cursor blinking test macOS * replace -fPIC with CMAKE_POSITION_INDEPENDENT_CODE flag. fix #132 * [appveyor | macOS] disable precise timer fix #131 * [TuiTerminal] phase 1 ver 0.1-showcase and example. Fixes #133 * [cmake] using GoogleTest module and macro for test. Fixes#128 * TODOs review * define specific runtime_error exception. Fixes # 139 * fixes #91 * [wont fix] snapshot testing on CI. Fixes #141 * publish test report and code coverage on analysis pipeline. Fixes #143 * publish test reports even if test task failed. Fixes #130 * add .gittribute * [lint] line ending LF * [lint] replace TABS with SPACES * [lint] end line LF. [azure-pipelines] cpplint analisys * [azure-pipelines] add cpplint job. Fixes #140 * compilers warning fixes #146 * Apply suggestions from code review --- .gitattribute | 2 + .gitignore | 10 +- CMakeLists.txt | 79 +- LICENSE | 42 +- README.md | 39 +- appveyor.yml | 18 +- azure-pipelines/analyzer.yml | 36 +- azure-pipelines/macos.yml | 2 + azure-pipelines/matrix.yml | 2 + azure-pipelines/templates/ci-steps.yml | 17 +- .../templates/cmake-test-steps.yml | 21 + azure-pipelines/templates/sonarcloud-job.yml | 36 +- azure-pipelines/variables/build_switches.yml | 1 + azure-pipelines/variables/global.yml | 2 +- cpplint.sh | 10 + sdl2-vga-terminal/CMakeLists.txt | 460 ++--- sdl2-vga-terminal/examples/CMakeLists.txt | 113 +- .../examples/sdl2-tui-terminal.cpp | 59 + .../examples/sdl2-vga-terminal-load-so.c | 309 ++-- .../examples/sdl2-vga-terminal-so.c | 107 +- .../examples/sdl2-vga-terminal.cpp | 429 ++--- sdl2-vga-terminal/include/vga-terminal.h | 20 +- sdl2-vga-terminal/src/TuiTerminal.cpp | 360 ++++ sdl2-vga-terminal/src/TuiTerminal.hpp | 70 + sdl2-vga-terminal/src/VgaTerminal.cpp | 222 ++- sdl2-vga-terminal/src/VgaTerminal.hpp | 49 +- sdl2-vga-terminal/src/Window.cpp | 108 +- sdl2-vga-terminal/src/Window.hpp | 50 +- .../src/exceptions/exceptions.hpp | 32 + sdl2-vga-terminal/src/tui/utils.cpp | 48 + sdl2-vga-terminal/src/tui/utils.hpp | 13 + sdl2-vga-terminal/src/vga-terminal.cpp | 24 +- sdl2-vga-terminal/src/vgafonts.h | 1542 ++++++++--------- sdl2-vga-terminal/src/vgapalette.h | 96 +- sdl2-vga-terminal/test/CMakeLists.txt | 168 +- sdl2-vga-terminal/test/Environment.hpp | 49 +- sdl2-vga-terminal/test/Snapshot.hpp | 117 ++ .../test/TuiTerminalSnapshotTest.cpp | 26 + .../test/VgaTerminalSnapshotTest.cpp | 65 + sdl2-vga-terminal/test/VgaTerminalTest.cpp | 617 +++++++ sdl2-vga-terminal/test/WindowTest.cpp | 19 + .../test/snapshot/TuiTerminal.Snapshot.png | Bin 0 -> 6544 bytes sdl2-vga-terminal/test/snapshotTest.cpp | 135 -- sdl2-vga-terminal/test/so-test.cpp | 20 +- sdl2-vga-terminal/test/tests.cpp | 514 ------ sdl2-vga-terminal/test/tui/utilsTest.cpp | 104 ++ sdl2-vga-terminal/test/valgrind/helgrind.cpp | 256 +-- .../test/valgrind/multithreading.cpp | 218 +-- sonar-project.properties | 4 +- 49 files changed, 3944 insertions(+), 2796 deletions(-) create mode 100644 .gitattribute create mode 100644 azure-pipelines/templates/cmake-test-steps.yml create mode 100644 cpplint.sh create mode 100644 sdl2-vga-terminal/examples/sdl2-tui-terminal.cpp create mode 100644 sdl2-vga-terminal/src/TuiTerminal.cpp create mode 100644 sdl2-vga-terminal/src/TuiTerminal.hpp create mode 100644 sdl2-vga-terminal/src/exceptions/exceptions.hpp create mode 100644 sdl2-vga-terminal/src/tui/utils.cpp create mode 100644 sdl2-vga-terminal/src/tui/utils.hpp create mode 100644 sdl2-vga-terminal/test/Snapshot.hpp create mode 100644 sdl2-vga-terminal/test/TuiTerminalSnapshotTest.cpp create mode 100644 sdl2-vga-terminal/test/VgaTerminalSnapshotTest.cpp create mode 100644 sdl2-vga-terminal/test/VgaTerminalTest.cpp create mode 100644 sdl2-vga-terminal/test/WindowTest.cpp create mode 100644 sdl2-vga-terminal/test/snapshot/TuiTerminal.Snapshot.png delete mode 100644 sdl2-vga-terminal/test/snapshotTest.cpp delete mode 100644 sdl2-vga-terminal/test/tests.cpp create mode 100644 sdl2-vga-terminal/test/tui/utilsTest.cpp diff --git a/.gitattribute b/.gitattribute new file mode 100644 index 00000000..032c1bd1 --- /dev/null +++ b/.gitattribute @@ -0,0 +1,2 @@ +* text=auto + diff --git a/.gitignore b/.gitignore index a3beb43b..b68bf332 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -/out/ -/.vs/ -/CmakeSettings.json -/build -.vscode/ +/out/ +/.vs/ +/CmakeSettings.json +/build +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 372e8553..5e4d45b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,39 +1,40 @@ -cmake_minimum_required (VERSION 3.16) - -if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) - set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") -endif() - -project ("sdl2-vga-terminal" VERSION 0.2.2 DESCRIPTION "Vga Terminal on SDL2") - - -################################ Packages #################################### -set (CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}) -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(CPACK_SYSTEM_NAME win64) - else() - set(CPACK_SYSTEM_NAME win32) - endif() -endif() -set(CPACK_PACKAGE_FILE_NAME ${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${CPACK_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}) -set(CPACK_SOURCE_GENERATOR "ZIP") -set(CPACK_GENERATOR "ZIP") -set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CMAKE_PROJECT_DESCRIPTION}) -include(CPack) - - -################################# Options #################################### -option(BUILD_SHARED_LIBS "build shared libs with C inteface" ON) -option(BUILD_EXAMPLES "build examples" ON) -include(CTest) -option(ENABLE_CODE_COVERAGE "compile Debug with code coverage" OFF) -option(BUILD_SNAPSHOT "build snapshot test" OFF) -include(CMakeDependentOption) -CMAKE_DEPENDENT_OPTION(TEST_DUMP_SNAPSHOT "build test to dump the expected output instead of verifing it" OFF -"BUILD_SNAPSHOT" OFF) -option(WITH_SDL2_STATIC "linking STATIC LIB with SDL2 STATIC" OFF) - -enable_testing() -add_subdirectory ("sdl2-vga-terminal") +cmake_minimum_required (VERSION 3.16) + +if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") +endif() + +project ("sdl2-vga-terminal" VERSION 0.3.0 DESCRIPTION "Vga Terminal on SDL2") + + +################################ Packages #################################### +set (CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}) +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CPACK_SYSTEM_NAME win64) + else() + set(CPACK_SYSTEM_NAME win32) + endif() +endif() +set(CPACK_PACKAGE_FILE_NAME ${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${CPACK_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}) +set(CPACK_SOURCE_GENERATOR "ZIP") +set(CPACK_GENERATOR "ZIP") +set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CMAKE_PROJECT_DESCRIPTION}) +include(CPack) + + +################################# Options #################################### +option(BUILD_SHARED_LIBS "build shared libs with C inteface" ON) +option(BUILD_EXAMPLES "build examples" ON) +include(CTest) +option(ENABLE_CODE_COVERAGE "compile Debug with code coverage" OFF) +option(BUILD_SNAPSHOT "build snapshot test" OFF) +include(CMakeDependentOption) +CMAKE_DEPENDENT_OPTION(TEST_DUMP_SNAPSHOT "build test to dump the expected output instead of verifing it" OFF +"BUILD_SNAPSHOT" OFF) +option(WITH_SDL2_STATIC "linking STATIC LIB with SDL2 STATIC" OFF) +option(HAVE_PRECISE_TIMER "if SDL2 timers are precise" ON) + +enable_testing() +add_subdirectory ("sdl2-vga-terminal") diff --git a/LICENSE b/LICENSE index f82e7bc5..40efeb23 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2020 Raffaello Bertini - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2020 Raffaello Bertini + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 999dfd40..3aa69c15 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,16 @@ there are 5 pipelines, 1 for each OS and one dedicated to "Analysis", plus 1 for matrix build. -- the CI pipelines related to each OS are building multiple times based on the below matrix. - The result of the tests are published in Azure Devops as well through `ctest -T Test` flag. +- The CI pipelines related to each OS are building and generating the artifacts. + + Only Linux is not runnig the tests due to missing video driver on CI. + + The test results are published in Azure Devops through `ctest -T Test` flag. -- the Analysis pipeline is analyzing the code, generating coverage and publish to codecov and SonarCloud -- the Matrix pipeline is an overkill so it is just triggered manually when required. - -The Matrix build is reflecting this table: +- The Analysis pipeline is analyzing the code, generating coverage and publish to codecov and SonarCloud. + it also performing a `cpplint` job and publish as artifact the result. +- The Matrix pipeline is an overkill so it is just triggered manually when required. + It is reflecting this table: | FLAGS\OS | Windows | Linux | macos | |:--------------------:|:------------------:|:------------------:|:------------------:| @@ -69,14 +72,12 @@ It should be on 16 colors in the classic way, but can support more thanks to SDL It is just a matter of fonts and a terminal grid for displaying texts. - ## Requirements - `SDL2` ## Compiling - These are the requirements to compile the project from source: - `cmake 3.16` @@ -113,9 +114,25 @@ The filename generated are based on the test that are running, ideally: `[Test-s Just as a convention. +## Tui Terminal (Experimental) + +This is just a show case and has not to be considered following the semantic versioning of the project, +it implies things might change with no objective reason at all. + +It might could be detached completely and be its own library using this one. + +At the moment is really very basic, error-prone and not well designed neither. + +There is an example too among the examples. + +### Screenshot + +This is a TUI screenshot used in the snapshot test too. + +![alt text](./sdl2-vga-terminal/test/snapshot/TuiTerminal.Snapshot.png "Title") ## Projects Idea to be done in the future -- `VT Snake` (retro-gaming style snake in an emulated DOS Text Mode) -- `VT Tetris` (retro-gaming style Tetris in an emulated DOS Text Mode) -- `VT Pong` (retro-gaming style Pong in an emulated DOS Text Mode) +- `VT Snake` (retro-gaming style snake in an emulated DOS Text Mode) +- `VT Tetris` (retro-gaming style Tetris in an emulated DOS Text Mode) +- `VT Pong` (retro-gaming style Pong in an emulated DOS Text Mode) diff --git a/appveyor.yml b/appveyor.yml index 2c5e09a5..9f9c5b76 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,6 +20,7 @@ configuration: environment: VCPKG_SCRIPT: scripts/buildsystems/vcpkg.cmake ENABLE_CODE_COVERAGE: OFF + HAVE_PRECISE_TIMER: ON matrix: allow_failures: @@ -47,7 +48,7 @@ for: environment: WS: /Users/appveyor/projects TRIPLET: $PLATFORM-osx -# ENABLE_CODE_COVERAGE: ON + HAVE_PRECISE_TIMER: OFF cache: #- $WS/vcpkg - $WS/vcpkg/installed @@ -56,20 +57,8 @@ for: - sh: brew install p7zip #lcov - sh: cd $WS && git clone https://github.com/Microsoft/vcpkg.git - sh: cd $APPVEYOR_BUILD_FOLDER - # /Library/Developer/CommandLineTools/usr/bin/llvm-cov - #- sh: sudo find / -name llvm-cov 2> /dev/null - #- sh: llvm-cov --help test_script: - sh: ctest -V - #- sh: find . -name *.gcda - #- sh: echo '#!/bin/bash' > g.sh - #- sh: echo 'exec /Library/Developer/CommandLineTools/usr/bin/llvm-cov gcov "$@"' >> g.sh - #- sh: chmod +x g.sh - #- sh: ./g.sh -f -b -u $(find . -name *.gcda) - #- sh: lcov --directory . --base-directory . --gcov-tool ./g.sh --capture -o cov.info - #- sh: lcov --remove cov.info '/Applications/*' --output-file coverage.info - #- sh: lcov --list coverage.info - #- sh: bash <(curl -s https://codecov.io/bash) -f coverage.info -t b8f07100-6985-49f7-aa4c-14e36f29ac80 skip_commits: files: @@ -83,7 +72,6 @@ skip_commits: cache: - C:\tools\vcpkg\installed - install: - cmd: if "%PLATFORM%" == "x64" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - cmd: if "%PLATFORM%" == "x86" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" @@ -104,7 +92,7 @@ build_script: - mkdir out - cd out - cmd: cmake -G "Ninja" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DWITH_SDL2_STATIC=OFF -DBUILD_SNAPSHOT=OFF -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/%VCPKG_SCRIPT% .. - - sh : cmake -DCMAKE_BUILD_TYPE=$CONFIGURATION -DWITH_SDL2_STATIC=ON -DBUILD_SNAPSHOT=OFF -DENABLE_CODE_COVERAGE=$ENABLE_CODE_COVERAGE -DCMAKE_TOOLCHAIN_FILE=$WS/vcpkg/$VCPKG_SCRIPT .. + - sh : cmake -DCMAKE_BUILD_TYPE=$CONFIGURATION -DWITH_SDL2_STATIC=ON -DBUILD_SNAPSHOT=OFF -DENABLE_CODE_COVERAGE=$ENABLE_CODE_COVERAGE -DHAVE_PRECISE_TIMER=$HAVE_PRECISE_TIMER -DCMAKE_TOOLCHAIN_FILE=$WS/vcpkg/$VCPKG_SCRIPT .. - cmake --build . test_script: diff --git a/azure-pipelines/analyzer.yml b/azure-pipelines/analyzer.yml index 7faaaf2a..f37681ac 100644 --- a/azure-pipelines/analyzer.yml +++ b/azure-pipelines/analyzer.yml @@ -53,20 +53,8 @@ stages: BUILD_EXAMPLES: OFF BUILD_SHARED_LIBS: ON ENABLE_CODE_COVERAGE: ON + HAVE_PRECISE_TIMER: OFF jobs: - # - template: 'templates/sonarcloud-job.yml' - # parameters: - # imageName: ${{ variables.windows_image }} - # jobName: SonarCloud_win - # jobDisplayName: SonarCloud (WIN) - # vcpkg_key_cache: $(CACHE_VCPKG_KEY) - # triplet: x64-windows - # arch: 64 - # build_type: Debug - # sonar_wrapper_url: 'https://sonarcloud.io/static/cpp/build-wrapper-win-x86.zip' - # build_wrapper: 'build-wrapper-win-x86\build-wrapper-win-x86-64.exe' - # build_wrapper_path: build/build-wrapper-win-x86 - # cmake_ignore_path: $(CMAKE_IGNORE_PATH_WIN) - template: 'templates/sonarcloud-job.yml' parameters: imageName: ${{ variables.mac_image }} @@ -78,3 +66,25 @@ stages: sonar_wrapper_url: 'https://sonarcloud.io/static/cpp/build-wrapper-macosx-x86.zip' build_wrapper: 'build-wrapper-macosx-x86/build-wrapper-macosx-x86' build_wrapper_path: build/build-wrapper-macosx-x86 + + ### the cmake-gen-build-steps should be geneneralized to accept different + ### arguments from the build-wrapper, and the build wrapper in this case + ### is scan-build tool, at the moment make it working, 2nd iteration + ### generalize that themplate. + - job: cpplint + pool: + vmImage: ${{ variables.mac_image }} + steps: + - script: pip install cpplint + displayName: install cpplint + - script: chmod +x cpplint.sh && ./cpplint.sh 2> cpplint.log || echo "-==*** ignoring linting warnings ***==-" + displayName: cpplint + continueOnError: true + # Publish (upload) a file or directory as a named artifact for the current run + - task: PublishPipelineArtifact@1 + inputs: + targetPath: cpplint.log + artifactName: 'cpplint.log' + - script: cat cpplint.log + displayName: cpplint result + diff --git a/azure-pipelines/macos.yml b/azure-pipelines/macos.yml index e8707b2d..d9ae8aba 100644 --- a/azure-pipelines/macos.yml +++ b/azure-pipelines/macos.yml @@ -43,6 +43,8 @@ stages: - stage: CI jobs: - job: macOS + variables: + HAVE_PRECISE_TIMER: OFF strategy: matrix: Debug: diff --git a/azure-pipelines/matrix.yml b/azure-pipelines/matrix.yml index 6604c5ea..309062ea 100644 --- a/azure-pipelines/matrix.yml +++ b/azure-pipelines/matrix.yml @@ -85,6 +85,8 @@ stages: - stage: matrix_macos displayName: Matrix MacOS dependsOn: Dep + variables: + HAVE_PRECISE_TIMER: OFF jobs: - template: 'templates/matrix-job.yml' parameters: diff --git a/azure-pipelines/templates/ci-steps.yml b/azure-pipelines/templates/ci-steps.yml index c8d4b8c9..b501dd11 100644 --- a/azure-pipelines/templates/ci-steps.yml +++ b/azure-pipelines/templates/ci-steps.yml @@ -64,20 +64,9 @@ steps: arch: ${{ parameters.arch }} #build_wrapper: - ${{ if eq(parameters.test, true) }}: - - script: ctest -C ${{ parameters.build_type }} -v -V -T Test - displayName: cmake test (ctest) - workingDirectory: build - - task: PublishTestResults@2 - inputs: - testResultsFormat: 'cTest' # Options: JUnit, NUnit, VSTest, xUnit, cTest - testResultsFiles: '**/Test.xml' - searchFolder: build # Optional - #mergeTestResults: false # Optional - #failTaskOnFailedTests: false # Optional - #testRunTitle: # Optional - #buildPlatform: # Optional - #buildConfiguration: # Optional - #publishRunAttachments: true # Optional + - template: 'cmake-test-steps.yml' + parameters: + build_type: ${{ parameters.build_type }} - ${{ if eq(parameters.install, true) }}: - script: cmake --build . --target install diff --git a/azure-pipelines/templates/cmake-test-steps.yml b/azure-pipelines/templates/cmake-test-steps.yml new file mode 100644 index 00000000..9a2f2a99 --- /dev/null +++ b/azure-pipelines/templates/cmake-test-steps.yml @@ -0,0 +1,21 @@ +parameters: + - name: build_type + displayName: Build Type + type: string + +steps: + - script: ctest -C ${{ parameters.build_type }} -v -V -T Test + displayName: cmake test (ctest) + workingDirectory: build + - task: PublishTestResults@2 + condition: succeededOrFailed() + inputs: + testResultsFormat: 'cTest' # Options: JUnit, NUnit, VSTest, xUnit, cTest + testResultsFiles: '**/Test.xml' + searchFolder: build # Optional + #mergeTestResults: false # Optional + #failTaskOnFailedTests: false # Optional + #testRunTitle: # Optional + #buildPlatform: # Optional + #buildConfiguration: # Optional + #publishRunAttachments: true # Optional diff --git a/azure-pipelines/templates/sonarcloud-job.yml b/azure-pipelines/templates/sonarcloud-job.yml index 01afbb99..309092b2 100644 --- a/azure-pipelines/templates/sonarcloud-job.yml +++ b/azure-pipelines/templates/sonarcloud-job.yml @@ -127,11 +127,10 @@ jobs: arch: ${{ parameters.arch }} build_wrapper: "${{ parameters.build_wrapper }} --out-dir bw-output" - - ${{ if eq(parameters.test, true) }}: - - script: ctest -C ${{ parameters.build_type }} - displayName: ctest - workingDirectory: build - # /usr/local/Cellar/llvm/10.0.0_3/bin/llvm-cov + - template: 'cmake-test-steps.yml' + parameters: + build_type: ${{ parameters.build_type }} + - bash: | echo '#!/bin/bash' > g.sh echo 'exec /usr/local/Cellar/llvm/10.0.0_3/bin/llvm-cov gcov "$@"' >> g.sh @@ -146,20 +145,35 @@ jobs: # condition: ne(variables['Agent.OS'], 'Windows_NT') - bash: | echo $OSTYPE - test $OSTYPE = "darwin19" && brew install lcov || apt-get install -y lcov - #brew install lcov - #echo "finding..." - #find . -name *.gcda - #echo "...." + test $OSTYPE = "darwin19" && brew install lcov || apt-get install -y lcov ./g.sh -f -b -u $(find . -name *.gcda) lcov --directory . --base-directory . --gcov-tool ./g.sh --capture -o cov.info lcov --remove cov.info '/Applications/*' --output-file coverage.info lcov --list coverage.info - bash <(curl -s https://codecov.io/bash) -f coverage.info -t b8f07100-6985-49f7-aa4c-14e36f29ac80 + #gcovr -r ../ --filter ../sdl2-vga-terminal/src -o sonarcube.xml --sonarqube + #gcovr -r ../ --filter ../sdl2-vga-terminal/src -o cobertura.xml --cobertura displayName: collect coverage data workingDirectory: build condition: ne(variables['Agent.OS'], 'Windows_NT') + - bash: bash <(curl -s https://codecov.io/bash) -f coverage.info -t b8f07100-6985-49f7-aa4c-14e36f29ac80s + displayName: codeCov + workingDirectory: build + continueOnError: true + - bash: | + curl https://raw.githubusercontent.com/eriwen/lcov-to-cobertura-xml/master/lcov_cobertura/lcov_cobertura.py -o lcov_cobertura.py + python lcov_cobertura.py coverage.info -o cobertura.xml + displayName: gen cobertura.xml + continueOnError: true + workingDirectory: build - task: SonarCloudAnalyze@1 - task: SonarCloudPublish@1 inputs: pollingTimeoutSec: ${{ parameters.publish_timeout }} + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: 'cobertura' #'JaCoCo' # Options: cobertura, jaCoCo + summaryFileLocation: build/cobertura.xml + pathToSources: sdl2-vga-terminal/src # Optional + #reportDirectory: build # Optional + #additionalCodeCoverageFiles: # Optional + #failIfCoverageEmpty: false # Optional diff --git a/azure-pipelines/variables/build_switches.yml b/azure-pipelines/variables/build_switches.yml index 49888b70..90adc661 100644 --- a/azure-pipelines/variables/build_switches.yml +++ b/azure-pipelines/variables/build_switches.yml @@ -5,3 +5,4 @@ variables: BUILD_EXAMPLES: ON BUILD_SNAPSHOT: OFF ENABLE_CODE_COVERAGE: OFF + HAVE_PRECISE_TIMER: ON diff --git a/azure-pipelines/variables/global.yml b/azure-pipelines/variables/global.yml index 09849b1a..38b0d8d7 100644 --- a/azure-pipelines/variables/global.yml +++ b/azure-pipelines/variables/global.yml @@ -1,5 +1,5 @@ variables: CACHE_VCPKG_KEY: v4 | vcpkg-root VCPKG_CMAKE: "$(Build.SourcesDirectory)/vcpkg/scripts/buildsystems/vcpkg.cmake" - CMAKE_ARGS: -DWITH_SDL2_STATIC=$(SDL2_STATIC) -DBUILD_TESTING=$(BUILD_TESTING) -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) -DBUILD_EXAMPLES=$(BUILD_EXAMPLES) -DBUILD_SNAPSHOT=$(BUILD_SNAPSHOT) -DENABLE_CODE_COVERAGE=$(ENABLE_CODE_COVERAGE) + CMAKE_ARGS: -DWITH_SDL2_STATIC=$(SDL2_STATIC) -DBUILD_TESTING=$(BUILD_TESTING) -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) -DBUILD_EXAMPLES=$(BUILD_EXAMPLES) -DBUILD_SNAPSHOT=$(BUILD_SNAPSHOT) -DENABLE_CODE_COVERAGE=$(ENABLE_CODE_COVERAGE) -DHAVE_PRECISE_TIMER=$(HAVE_PRECISE_TIMER) CMAKE_IGNORE_PATH_WIN: "C:/MinGW/bin;C:/Strawberry/c/bin;C:/Program Files (x86)/LLVM/bin;C:/ProgramData/chocolatey/bin" diff --git a/cpplint.sh b/cpplint.sh new file mode 100644 index 00000000..3410d88e --- /dev/null +++ b/cpplint.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cpplint --recursive --linelength=120 \ + --exclude=sdl2-vga-terminal/src/vgapalette.h \ + --filter=-legal/copyright,-build/include_order,-whitespace/braces\ +,-whitespace/line_length,-build/include_subdir,-whitespace/indent\ +,-whitespace/newline,-build/namespaces,-readability/braces,-build/c++11\ +,-readability/todo,-whitespace/comments,-readability/utf8\ +,-runtime/threadsafe_fn,-runtime/indentation_namespace \ + sdl2-vga-terminal/ diff --git a/sdl2-vga-terminal/CMakeLists.txt b/sdl2-vga-terminal/CMakeLists.txt index aaf19f06..b4c392b4 100644 --- a/sdl2-vga-terminal/CMakeLists.txt +++ b/sdl2-vga-terminal/CMakeLists.txt @@ -1,226 +1,234 @@ -cmake_minimum_required (VERSION 3.16) - - -set (CMAKE_CXX_STANDARD 17) -set (CMAKE_DEBUG_POSTFIX d) - -find_package(SDL2 CONFIG REQUIRED) - -configure_file(version.h.in version.h) - -if(WITH_SDL2_STATIC) - set(LIB_SDL2 SDL2::SDL2-static) -else() - set(LIB_SDL2 SDL2::SDL2) -endif() - -if (WIN32) - set(LIB_SDL2main SDL2::SDL2main) -endif() - -########################### Static Lib ####################################### -set(LIB_NAME vga-terminal-static) -set(LIB_CONF ${LIB_NAME}-config) -set(LIB_VER ${LIB_CONF}-version) -include(CMakePackageConfigHelpers) - -add_library(${LIB_NAME} STATIC) -install( - TARGETS ${LIB_NAME} - EXPORT ${LIB_CONF} - DESTINATION static/lib - PUBLIC_HEADER DESTINATION static/include -) -install(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/src/VgaTerminal.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/Window.hpp - DESTINATION static/include -) - -write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake - VERSION ${CMAKE_PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion - ) - -export(TARGETS ${LIB_NAME} - FILE ${CMAKE_BINARY_DIR}/${LIB_NAME}.cmake - NAMESPACE VgaTerminal:: -) - -install(EXPORT ${LIB_CONF} - DESTINATION static/cmake - NAMESPACE VgaTerminal:: -) -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake - DESTINATION static/cmake -) -target_include_directories(${LIB_NAME} PUBLIC - $> - $ - $ -) -target_sources(${LIB_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/VgaTerminal.cpp -) - -target_link_libraries(${LIB_NAME} PUBLIC ${LIB_SDL2}) -if(NOT (WITH_SDL2_STATIC)) - install(FILES - $ - DESTINATION static/lib - ) -endif() - -unset(LIB_NAME) -unset(LIB_CONF) -unset(LIB_VER) - -############################ Shared lib ###################################### -if (BUILD_SHARED_LIBS) - set(LIB_NAME vga-terminal) - set(LIB_CONF ${LIB_NAME}-config) - set(LIB_VER ${LIB_CONF}-version) - - include(GenerateExportHeader) - - add_library(${LIB_NAME} SHARED) - add_dependencies(${LIB_NAME} vga-terminal-static) - generate_export_header( - ${LIB_NAME} - BASE_NAME ${LIB_NAME} - EXPORT_MACRO_NAME VGA_TERMINAL_EXPORT - EXPORT_FILE_NAME ${LIB_NAME}-export.h - STATIC_DEFINE ${LIB_NAME}-lib_BUILD_AS_STATIC - ) - install( - TARGETS ${LIB_NAME} - EXPORT ${LIB_CONF} - DESTINATION lib - PUBLIC_HEADER DESTINATION include - ) - install(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/include/vga-terminal.h - $/${LIB_NAME}-export.h - DESTINATION include - ) - if (NOT (WITH_SDL2_STATIC)) - install(FILES - $ - DESTINATION lib - ) - endif() - - write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake - VERSION ${CMAKE_PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion - ) - - export(TARGETS vga-terminal - FILE ${CMAKE_BINARY_DIR}/${LIB_NAME}.cmake - ) - install(EXPORT - ${LIB_CONF} DESTINATION cmake - ) - - install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake - DESTINATION cmake - ) - target_include_directories(${LIB_NAME} PUBLIC - $> - $ - $ - ) - target_sources(${LIB_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src/vga-terminal.cpp - ) - target_link_libraries(${LIB_NAME} vga-terminal-static) - - unset(LIB_NAME) - unset(LIB_CONF) - unset(LIB_VER) -endif() - -######################## add compiler options ################################ -if(CMAKE_CXX_COMPILER_ID MATCHES "^MSVC") -# @see https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=vs-2019 - - target_compile_options(vga-terminal-static PRIVATE /W4 #/WX - $<$:/Od /GR /GS /Gs /guard:cf /RTC1c /D_ALLOW_RTCc_IN_STL> - $<$:/O2 /Ot /GA /GL /Gw> - ) - if (BUILD_SHARED_LIBS) - target_compile_options(vga-terminal PRIVATE /W4 #/WX - $<$:/Od /GR /GS /Gs /guard:cf /RTC1c /D_ALLOW_RTCc_IN_STL> - $<$:/O2 /Ot /GA /GL /Gw> - ) - endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES "^GNU") - target_compile_options(vga-terminal-static PRIVATE -Wall -Wextra -pedantic -fPIC - $<$: - -O0;-D_GLIBCXX_DEBUG;-D_GLIBCXX_ASSERTIONS;-fexceptions; - -W; -Wshadow; -Wunused-variable; - -Wunused-parameter; -Wunused-function; -Wunused; -Wno-system-headers; - -Wno-deprecated; -Woverloaded-virtual; -Wwrite-strings; - > - #$<$:-O2;-fexceptions;-fstack-clash-protection;-D_FORTIFY_SOURCE=2> - $<$:-O2;-fexceptions;-D_FORTIFY_SOURCE=2> - ) #-Werror) - - if (ENABLE_CODE_COVERAGE) - target_compile_options(vga-terminal-static PRIVATE - $<$: -fprofile-arcs; -ftest-coverage;> - ) - target_link_options(vga-terminal-static PRIVATE $<$:-fprofile-arcs; -ftest-coverage; --coverage;>) - endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang") - target_compile_options(vga-terminal-static PRIVATE -WCL4 -Wabstract-vbase-init -Wassign-enum - -Watomic-implicit-seq-cst -Watomic-properties -Wbad-function-cast -Wbinary-literal - ) - - if (WIN32) - set(LINK_SUBSYS_WIN /subsystem:windows) - message(STATUS ${LINK_SUBSYS_WIN}) - target_link_options(vga-terminal-static PUBLIC ${LINK_SUBSYS_WIN}) - elseif(UNIX) - target_compile_options(vga-terminal-static PRIVATE -fPIC - $<$: -g;> - $<$:-O2;> - ) - - if(ENABLE_CODE_COVERAGE) - target_compile_options(vga-terminal-static PRIVATE - $<$:-c;-fprofile-arcs; -ftest-coverage;> - ) - target_link_options(vga-terminal-static PUBLIC $<$: -ftest-coverage;-fprofile-arcs; --coverage;>) - #target_link_options(vga-terminal-static PUBLIC $<$: -fprofile-instr-generate; -fcoverage-mapping;>) - endif() - else() - message(ERROR "Unknown OS") - endif() -else() - message(WARNING ${CMAKE_CXX_COMPILER_ID}) -endif() - -message("target interface compiler options:") -get_target_property(vga-terminal-static_copts vga-terminal-static COMPILE_OPTIONS) -message(STATUS "vga-terminal-static " ${vga-terminal-static_copts}) -unset(vga-terminal-static_copts) - - - - - -################################ Examples #################################### -if(BUILD_EXAMPLES) - add_subdirectory("examples") -endif() - -############################### tests ######################################## -if(BUILD_TESTING) -add_subdirectory("test") -endif() +cmake_minimum_required (VERSION 3.16) + + +set (CMAKE_CXX_STANDARD 17) +set (CMAKE_DEBUG_POSTFIX d) + +find_package(SDL2 CONFIG REQUIRED) + +configure_file(version.h.in version.h) + +if(WITH_SDL2_STATIC) + set(LIB_SDL2 SDL2::SDL2-static) +else() + set(LIB_SDL2 SDL2::SDL2) +endif() + +if (WIN32) + set(LIB_SDL2main SDL2::SDL2main) +endif() + +if(HAVE_PRECISE_TIMER) +else() + add_compile_definitions(NO_PRECISE_TIMER) +endif() + +########################### Static Lib ####################################### +set(LIB_NAME vga-terminal-static) +set(LIB_CONF ${LIB_NAME}-config) +set(LIB_VER ${LIB_CONF}-version) +include(CMakePackageConfigHelpers) + +add_library(${LIB_NAME} STATIC) +set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) +install( + TARGETS ${LIB_NAME} + EXPORT ${LIB_CONF} + DESTINATION static/lib + PUBLIC_HEADER DESTINATION static/include +) +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/VgaTerminal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Window.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/TuiTerminal.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/exceptions/exceptions.hpp + DESTINATION static/include +) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake + VERSION ${CMAKE_PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion + ) + +export(TARGETS ${LIB_NAME} + FILE ${CMAKE_BINARY_DIR}/${LIB_NAME}.cmake + NAMESPACE VgaTerminal:: +) + +install(EXPORT ${LIB_CONF} + DESTINATION static/cmake + NAMESPACE VgaTerminal:: +) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake + DESTINATION static/cmake +) +target_include_directories(${LIB_NAME} PUBLIC + $> + $ + $ +) +target_sources(${LIB_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/VgaTerminal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/TuiTerminal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/tui/utils.cpp +) + +target_link_libraries(${LIB_NAME} PUBLIC ${LIB_SDL2}) +if(NOT (WITH_SDL2_STATIC)) + install(FILES + $ + DESTINATION static/lib + ) +endif() + +unset(LIB_NAME) +unset(LIB_CONF) +unset(LIB_VER) + +############################ Shared lib ###################################### +if (BUILD_SHARED_LIBS) + set(LIB_NAME vga-terminal) + set(LIB_CONF ${LIB_NAME}-config) + set(LIB_VER ${LIB_CONF}-version) + + include(GenerateExportHeader) + + add_library(${LIB_NAME} SHARED) + add_dependencies(${LIB_NAME} vga-terminal-static) + generate_export_header( + ${LIB_NAME} + BASE_NAME ${LIB_NAME} + EXPORT_MACRO_NAME VGA_TERMINAL_EXPORT + EXPORT_FILE_NAME ${LIB_NAME}-export.h + STATIC_DEFINE ${LIB_NAME}-lib_BUILD_AS_STATIC + ) + install( + TARGETS ${LIB_NAME} + EXPORT ${LIB_CONF} + DESTINATION lib + PUBLIC_HEADER DESTINATION include + ) + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/vga-terminal.h + $/${LIB_NAME}-export.h + DESTINATION include + ) + if (NOT (WITH_SDL2_STATIC)) + install(FILES + $ + DESTINATION lib + ) + endif() + + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake + VERSION ${CMAKE_PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion + ) + + export(TARGETS vga-terminal + FILE ${CMAKE_BINARY_DIR}/${LIB_NAME}.cmake + ) + install(EXPORT + ${LIB_CONF} DESTINATION cmake + ) + + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${LIB_VER}.cmake + DESTINATION cmake + ) + target_include_directories(${LIB_NAME} PUBLIC + $> + $ + $ + ) + target_sources(${LIB_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/vga-terminal.cpp + ) + target_link_libraries(${LIB_NAME} vga-terminal-static) + + unset(LIB_NAME) + unset(LIB_CONF) + unset(LIB_VER) +endif() + +######################## add compiler options ################################ +if(CMAKE_CXX_COMPILER_ID MATCHES "^MSVC") +# @see https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=vs-2019 + + target_compile_options(vga-terminal-static PRIVATE /W4 #/WX + $<$:/Od /GR /GS /Gs /guard:cf /RTC1c /D_ALLOW_RTCc_IN_STL> + $<$:/O2 /Ot /GA /GL /Gw> + ) + if (BUILD_SHARED_LIBS) + target_compile_options(vga-terminal PRIVATE /W4 #/WX + $<$:/Od /GR /GS /Gs /guard:cf /RTC1c /D_ALLOW_RTCc_IN_STL> + $<$:/O2 /Ot /GA /GL /Gw> + ) + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "^GNU") + target_compile_options(vga-terminal-static PRIVATE -Wall -Wextra -pedantic #-fPIC + $<$: + -O0;-D_GLIBCXX_DEBUG;-D_GLIBCXX_ASSERTIONS;-fexceptions; + -W; -Wshadow; -Wunused-variable; + -Wunused-parameter; -Wunused-function; -Wunused; -Wno-system-headers; + -Wno-deprecated; -Woverloaded-virtual; -Wwrite-strings; + > + #$<$:-O2;-fexceptions;-fstack-clash-protection;-D_FORTIFY_SOURCE=2> + $<$:-O2;-fexceptions;-D_FORTIFY_SOURCE=2> + ) #-Werror) + + if (ENABLE_CODE_COVERAGE) + target_compile_options(vga-terminal-static PRIVATE + $<$: -fprofile-arcs; -ftest-coverage;> + ) + target_link_options(vga-terminal-static PUBLIC $<$:-fprofile-arcs; -ftest-coverage; --coverage;>) + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang") + target_compile_options(vga-terminal-static PRIVATE -WCL4 -Wabstract-vbase-init -Wassign-enum + -Watomic-implicit-seq-cst -Watomic-properties -Wbad-function-cast -Wbinary-literal + ) + + if (WIN32) + set(LINK_SUBSYS_WIN /subsystem:windows) + message(STATUS ${LINK_SUBSYS_WIN}) + target_link_options(vga-terminal-static PUBLIC ${LINK_SUBSYS_WIN}) + elseif(UNIX) + target_compile_options(vga-terminal-static PRIVATE #-fPIC + $<$: -g;> + $<$:-O2;> + ) + + if(ENABLE_CODE_COVERAGE) + target_compile_options(vga-terminal-static PRIVATE + $<$:-c;-fprofile-arcs; -ftest-coverage;> + ) + target_link_options(vga-terminal-static PUBLIC $<$: -ftest-coverage;-fprofile-arcs; --coverage;>) + #target_link_options(vga-terminal-static PUBLIC $<$: -fprofile-instr-generate; -fcoverage-mapping;>) + endif() + else() + message(ERROR "Unknown OS") + endif() +else() + message(WARNING ${CMAKE_CXX_COMPILER_ID}) +endif() + +message("target interface compiler options:") +get_target_property(vga-terminal-static_copts vga-terminal-static COMPILE_OPTIONS) +message(STATUS "vga-terminal-static " ${vga-terminal-static_copts}) +unset(vga-terminal-static_copts) + + +################################ Examples #################################### +if(BUILD_EXAMPLES) + add_subdirectory("examples") +endif() + + +############################### tests ######################################## +if(BUILD_TESTING) + add_subdirectory("test") +endif() diff --git a/sdl2-vga-terminal/examples/CMakeLists.txt b/sdl2-vga-terminal/examples/CMakeLists.txt index a88846e0..e84079b1 100644 --- a/sdl2-vga-terminal/examples/CMakeLists.txt +++ b/sdl2-vga-terminal/examples/CMakeLists.txt @@ -1,33 +1,80 @@ -cmake_minimum_required (VERSION 3.16) - -############################## Main Example ################################## -add_executable (${PROJECT_NAME} "sdl2-vga-terminal.cpp") -add_dependencies(${PROJECT_NAME} vga-terminal-static) -target_link_libraries(${PROJECT_NAME} ${LIB_SDL2main} vga-terminal-static) - -if (BUILD_SHARED_LIBS) -################## C example using SO/DLL with lazy loading ################## - add_executable (${PROJECT_NAME}-so "sdl2-vga-terminal-so.c") - add_dependencies(${PROJECT_NAME}-so vga-terminal) - target_link_libraries(${PROJECT_NAME}-so ${LIB_SDL2main} vga-terminal) - add_custom_command(TARGET "${PROJECT_NAME}-so" POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - if(MSVC) - target_link_options(${PROJECT_NAME}-so PRIVATE - "/INCREMENTAL" - "/DELAYLOAD:$" - "/DELAY:UNLOAD" - ) - endif() - - -################## C example using SO/DLL run-time loading ################## - add_executable (${PROJECT_NAME}-load-so "sdl2-vga-terminal-load-so.c") - target_link_libraries(${PROJECT_NAME}-load-so PUBLIC ${LIB_SDL2main} ${LIB_SDL2} ${CMAKE_DL_LIBS}) - target_link_options(${PROJECT_NAME}-load-so PUBLIC ${LINK_SUBSYS_WIN}) - - add_custom_command(TARGET "${PROJECT_NAME}-load-so" POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) -endif() +cmake_minimum_required (VERSION 3.16) + +### Macro ### +macro(macro_example) # ${ARGN} link libraries + set(prefix EXAMPLE) + set(flags COPY_LIB NONE) + set(singleValues EXE FILE) + set(multiValues DEPS LINKS) + + include(CMakeParseArguments) + cmake_parse_arguments(${prefix} "${flags}" "${singleValues}" "${multiValues}" ${ARGN}) + #message("${EXE} - ${FILE} - ${DEPS} - ${LINKS}") + #message("EXE====${EXAMPLE_EXE}") + #message("IS NONE: ${EXAMPLE_NONE}") + #message("IS CPLIB: ${EXAMPLE_COPY_LIB}") + #message("EXE: ${EXAMPLE_EXE}") + #message("FILE: ${EXAMPLE_FILE}") + #message("DEP: ${EXAMPLE_DEPS}") + #message("LINKS: ${EXAMPLE_LINKS}") + add_executable (${EXAMPLE_EXE} ${EXAMPLE_FILE}) + add_dependencies(${EXAMPLE_EXE} ${EXAMPLE_DEPS}) + target_link_libraries(${EXAMPLE_EXE} ${EXAMPLE_LINKS}) + if(${EXAMPLE_COPY_LIB}) + #message("===============EXAMPLE COPY LIB") + foreach(TF IN ITEMS ${EXAMPLE_DEPS}) + #message("++++ TF= ${TF} ++++") + add_custom_command( + TARGET ${EXAMPLE_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + endforeach() + endif() +endmacro() + +############################## Main Example ################################## +macro_example( + EXE "${PROJECT_NAME}" + FILE "sdl2-vga-terminal.cpp" + DEPS vga-terminal-static + LINKS ${LIB_SDL2main} vga-terminal-static + NONE +) + +############################### TUI Example ################################### +macro_example( + EXE "${PROJECT_NAME}-tui" + FILE "sdl2-tui-terminal.cpp" + DEPS vga-terminal-static + LINKS ${LIB_SDL2main} vga-terminal-static + NONE +) + +if (BUILD_SHARED_LIBS) +################## C example using SO/DLL with lazy loading ################## + macro_example( + EXE ${PROJECT_NAME}-so + FILE "sdl2-vga-terminal-so.c" + DEPS vga-terminal + LINKS ${LIB_SDL2main} vga-terminal + COPY_LIB + ) + + if(MSVC) + target_link_options(${PROJECT_NAME}-so PRIVATE + "/INCREMENTAL" + "/DELAYLOAD:$" + "/DELAY:UNLOAD" + ) + endif() + + +################## C example using SO/DLL run-time loading ################## + macro_example( + EXE ${PROJECT_NAME}-load-so + FILE "sdl2-vga-terminal-load-so.c" + DEPS vga-terminal + LINKS PUBLIC ${LIB_SDL2main} ${LIB_SDL2} ${CMAKE_DL_LIBS} + ) + target_link_options(${PROJECT_NAME}-load-so PUBLIC ${LINK_SUBSYS_WIN}) +endif() diff --git a/sdl2-vga-terminal/examples/sdl2-tui-terminal.cpp b/sdl2-vga-terminal/examples/sdl2-tui-terminal.cpp new file mode 100644 index 00000000..5163107a --- /dev/null +++ b/sdl2-vga-terminal/examples/sdl2-tui-terminal.cpp @@ -0,0 +1,59 @@ +// VgaTerminal TUI example + +#include + +int main(int argc, char* argv[]) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + + TuiTerminal tui = TuiTerminal("Tui Example", "a retro TUI style emulator"); + int pb1 = 0; + int pb1Max = 50; + int pb2 = 0; + int pb2Max = 3; + bool quit = false; + + // the draw method has to be the first to be called + // because of the background, otherwise + // everything else would be overwritten... (at the moment) + tui.draw(); + tui.drawSingleBorderDialog({ 30, 0, 40, 4 }, 11, 8, "Joshua", "GREETINGS PROFESSOR FALKEN."); + tui.drawDialog({ 20, 7, 40, 10 }, 15, 1, "Install", "Status"); + + while (!quit) + { + tui.progressBar(false, false, 24, 11, 20, pb2, pb2Max); + tui.progressBar(true, true, 24, 13, 20, pb1, pb1Max); + tui.render(); + + pb1++; + if (pb1 > pb1Max) { + pb1 = 0; + pb2++; + } + + if (pb2 > pb2Max) { + quit = true; + } + + SDL_Delay(10); + } + + tui.drawSingleBorderDialog({ 30, 10, 20, 3 }, 15, 1, "", "Press any key..."); + tui.render(); + // press a key... + SDL_Event event; + bool keypressed = false; + while (!keypressed) { + SDL_WaitEvent(&event); + if (event.type == SDL_KEYDOWN) { + keypressed = true; + } + } + + SDL_Quit(); + return 0; +} diff --git a/sdl2-vga-terminal/examples/sdl2-vga-terminal-load-so.c b/sdl2-vga-terminal/examples/sdl2-vga-terminal-load-so.c index f00abc56..50c81553 100644 --- a/sdl2-vga-terminal/examples/sdl2-vga-terminal-load-so.c +++ b/sdl2-vga-terminal/examples/sdl2-vga-terminal-load-so.c @@ -1,155 +1,154 @@ -/******************************************** - * USING THE SO/DLL in a C program example * - * The DLL/SO is loaded at run-time. * - ********************************************/ - -#include -#include -#include - -typedef void VGA_Terminal; - -#ifdef WIN32 - -#include - -typedef void(__cdecl* PROCWRITEXY)(VGA_Terminal*, uint8_t, uint8_t, char* str, uint8_t, uint8_t); -typedef void(__cdecl* PROCDESTROY)(VGA_Terminal*); -typedef void(__cdecl* PROCRENDER)(VGA_Terminal*); -typedef VGA_Terminal* (__cdecl* PROCINIT)(); -#endif - -#ifdef linux - -#include - -#endif - -#if defined(DEBUG) || !defined(NDBEBUG) - -#define VGA_SO_NAME "vga-terminald" - -#else - -#define VGA_SO_NAME "vga-terminal" - -#endif - -#ifdef WIN32 - -void win32() -{ - const char* soname = TEXT(VGA_SO_NAME ".dll"); - HINSTANCE hinstLib; - PROCINIT ProcAddInit = NULL; - PROCDESTROY ProcAddDestroy = NULL; - PROCWRITEXY ProcAddWriteXY = NULL; - PROCRENDER ProcAddRender = NULL; - BOOL fFreeResult; - BOOL fRunTimeLinkSuccess = SDL_FALSE; - - printf("loading library: %s\n", soname); - - hinstLib = LoadLibrary(soname); - if (hinstLib != NULL) - { - ProcAddInit = (PROCINIT)GetProcAddress(hinstLib, "VGA_TERMINAL_init"); - ProcAddDestroy = (PROCDESTROY)GetProcAddress(hinstLib, "VGA_TERMINAL_destroy"); - ProcAddWriteXY = (PROCWRITEXY)GetProcAddress(hinstLib, "VGA_TERMINAL_writeXY"); - ProcAddRender = (PROCRENDER)GetProcAddress(hinstLib, "VGA_TERMINAL_render"); - - // If the function address is valid, call the function. - - if (NULL != ProcAddInit && NULL != ProcAddDestroy && NULL != ProcAddWriteXY && NULL != ProcAddRender) - { - fRunTimeLinkSuccess = SDL_TRUE; - VGA_Terminal* term = ProcAddInit(); - ProcAddWriteXY(term, 0, 0, "GREETINGS PROFESSOR FALKENS.", 10, 0); - ProcAddRender(term); - SDL_Delay(1000); - ProcAddDestroy(term); - } - // Free the DLL module. - fFreeResult = FreeLibrary(hinstLib); - if (!fFreeResult) { - fprintf(stderr, "unable to unload library\n"); - } - else { - printf("library unloaded.\n"); - } - } - - // If unable to call the DLL function, use an alternative. - if (!fRunTimeLinkSuccess) { - DWORD dw = GetLastError(); - - fprintf(stderr, "failed to load the DLL. Error %lu\n", dw); - } -} -#endif - -#ifdef linux -void lnx() -{ - const char* soname = "./lib" VGA_SO_NAME ".so"; - void* handle = dlopen(soname, RTLD_NOW); - - if (handle) { - char* error; - - VGA_Terminal* (*init)(void); - void (*destroy)(VGA_Terminal*); - void (*writeXY)(VGA_Terminal*, uint8_t, uint8_t, char* str, uint8_t, uint8_t); - - init = dlsym(handle, "VGA_TERMINAL_init"); - if ((error = dlerror()) != NULL) { - fputs(error, stderr); - exit(1); - } - - destroy = dlsym(handle, "VGA_TERMINAL_destroy"); - if ((error = dlerror()) != NULL) { - fputs(error, stderr); - exit(1); - } - - writeXY = dlsym(handle, "VGA_TERMINAL_writeXY"); - if ((error = dlerror()) != NULL) { - fputs(error, stderr); - exit(1); - } - - - VGA_Terminal* term = (*init)(); - (*writeXY)(term, 0, 0, "test", 10, 0); - SDL_Delay(1000); - (*destroy)(term); - - - dlclose(handle); - } - else { - fprintf(stderr, "unable to load SO. Error %s\n", dlerror()); - } - -} -#endif - -int main(int argc, char* argv[]) -{ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); - return 1; - } - - -#ifdef WIN32 - win32(); -#endif -#ifdef linux - lnx(); -#endif - - SDL_Quit(); - return 0; -} +/******************************************** + * USING THE SO/DLL in a C program example * + * The DLL/SO is loaded at run-time. * + ********************************************/ + +#include +#include +#include + +typedef void VGA_Terminal; + +#ifdef WIN32 + +#include + +typedef void(__cdecl* PROCWRITEXY)(VGA_Terminal*, uint8_t, uint8_t, char* str, uint8_t, uint8_t); +typedef void(__cdecl* PROCDESTROY)(VGA_Terminal*); +typedef void(__cdecl* PROCRENDER)(VGA_Terminal*); +typedef VGA_Terminal* (__cdecl* PROCINIT)(); +#endif + +#ifdef linux + +#include + +#endif + +#if defined(DEBUG) || !defined(NDBEBUG) + +#define VGA_SO_NAME "vga-terminald" + +#else + +#define VGA_SO_NAME "vga-terminal" + +#endif + +#ifdef WIN32 + +void win32() +{ + const char* soname = TEXT(VGA_SO_NAME ".dll"); + HINSTANCE hinstLib; + PROCINIT ProcAddInit = NULL; + PROCDESTROY ProcAddDestroy = NULL; + PROCWRITEXY ProcAddWriteXY = NULL; + PROCRENDER ProcAddRender = NULL; + BOOL fFreeResult; + BOOL fRunTimeLinkSuccess = SDL_FALSE; + + printf("loading library: %s\n", soname); + + hinstLib = LoadLibrary(soname); + if (hinstLib != NULL) + { + ProcAddInit = (PROCINIT)GetProcAddress(hinstLib, "VGA_TERMINAL_init"); + ProcAddDestroy = (PROCDESTROY)GetProcAddress(hinstLib, "VGA_TERMINAL_destroy"); + ProcAddWriteXY = (PROCWRITEXY)GetProcAddress(hinstLib, "VGA_TERMINAL_writeXY"); + ProcAddRender = (PROCRENDER)GetProcAddress(hinstLib, "VGA_TERMINAL_render"); + + // If the function address is valid, call the function. + + if (NULL != ProcAddInit && NULL != ProcAddDestroy && NULL != ProcAddWriteXY && NULL != ProcAddRender) + { + fRunTimeLinkSuccess = SDL_TRUE; + VGA_Terminal* term = ProcAddInit(); + ProcAddWriteXY(term, 0, 0, "GREETINGS PROFESSOR FALKENS.", 10, 0); + ProcAddRender(term); + SDL_Delay(1000); + ProcAddDestroy(term); + } + // Free the DLL module. + fFreeResult = FreeLibrary(hinstLib); + if (!fFreeResult) { + fprintf(stderr, "unable to unload library\n"); + } + else { + printf("library unloaded.\n"); + } + } + + // If unable to call the DLL function, use an alternative. + if (!fRunTimeLinkSuccess) { + DWORD dw = GetLastError(); + + fprintf(stderr, "failed to load the DLL. Error %lu\n", dw); + } +} +#endif + +#ifdef linux +void lnx() +{ + const char* soname = "./lib" VGA_SO_NAME ".so"; + void* handle = dlopen(soname, RTLD_NOW); + + if (handle) { + char* error; + + VGA_Terminal* (*init)(void); + void (*destroy)(VGA_Terminal*); + void (*writeXY)(VGA_Terminal*, uint8_t, uint8_t, char* str, uint8_t, uint8_t); + + init = dlsym(handle, "VGA_TERMINAL_init"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } + + destroy = dlsym(handle, "VGA_TERMINAL_destroy"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } + + writeXY = dlsym(handle, "VGA_TERMINAL_writeXY"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } + + + VGA_Terminal* term = (*init)(); + (*writeXY)(term, 0, 0, "test", 10, 0); + SDL_Delay(1000); + (*destroy)(term); + + + dlclose(handle); + } + else { + fprintf(stderr, "unable to load SO. Error %s\n", dlerror()); + } +} +#endif + +int main(int argc, char* argv[]) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + + +#ifdef WIN32 + win32(); +#endif +#ifdef linux + lnx(); +#endif + + SDL_Quit(); + return 0; +} diff --git a/sdl2-vga-terminal/examples/sdl2-vga-terminal-so.c b/sdl2-vga-terminal/examples/sdl2-vga-terminal-so.c index aa24f88f..b39f542f 100644 --- a/sdl2-vga-terminal/examples/sdl2-vga-terminal-so.c +++ b/sdl2-vga-terminal/examples/sdl2-vga-terminal-so.c @@ -1,54 +1,53 @@ -/******************************************** - * USING THE SO/DLL in a C program example * - * The DLL/SO is linked at compile time. * - ********************************************/ - -#include -#include -#include - -#ifdef WIN32 -# include -# include -# pragma comment(lib, "delayimp") -#endif - - -int main(int argc, char* argv[]) -{ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); - return 1; - } - - VGA_Terminal* term = VGA_TERMINAL_init(); - - VGA_TERMINAL_writeXY(term, 0, 0, "GREETINGS PROFESSOR FALKEN.", 10, 0); - // emulating the main even loop few times - // just to show the cursor blinking.... - int quit = 6; - SDL_Event e; - while (quit--) { - VGA_TERMINAL_render(term); - do { - SDL_WaitEvent(&e); - } while (e.type != SDL_USEREVENT && e.user.type != SDL_USEREVENT); - - } - - VGA_TERMINAL_destroy(term); - -#ifdef WIN32 -# ifndef NDEBUG -# define PFIX "d" -# else -# define PFIX "" -# endif - int t = __FUnloadDelayLoadedDLL2("vga-terminal" PFIX ".dll"); - printf("unloaded? : %d\n", t); - getchar(); -#endif // WIN32 - - SDL_Quit(); - return 0; -} +/******************************************** + * USING THE SO/DLL in a C program example * + * The DLL/SO is linked at compile time. * + ********************************************/ + +#include +#include +#include + +#ifdef WIN32 +# include +# include +# pragma comment(lib, "delayimp") +#endif + + +int main(int argc, char* argv[]) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + + VGA_Terminal* term = VGA_TERMINAL_init(); + + VGA_TERMINAL_writeXY(term, 0, 0, "GREETINGS PROFESSOR FALKEN.", 10, 0); + // emulating the main even loop few times + // just to show the cursor blinking.... + int quit = 6; + SDL_Event e; + while (quit--) { + VGA_TERMINAL_render(term); + do { + SDL_WaitEvent(&e); + } while (e.type != SDL_USEREVENT && e.user.type != SDL_USEREVENT); + } + + VGA_TERMINAL_destroy(term); + +#ifdef WIN32 +# ifndef NDEBUG +# define PFIX "d" +# else +# define PFIX "" +# endif + int t = __FUnloadDelayLoadedDLL2("vga-terminal" PFIX ".dll"); + printf("unloaded? : %d\n", t); + getchar(); +#endif // WIN32 + + SDL_Quit(); + return 0; +} diff --git a/sdl2-vga-terminal/examples/sdl2-vga-terminal.cpp b/sdl2-vga-terminal/examples/sdl2-vga-terminal.cpp index ffe5a258..ba8fd0de 100644 --- a/sdl2-vga-terminal/examples/sdl2-vga-terminal.cpp +++ b/sdl2-vga-terminal/examples/sdl2-vga-terminal.cpp @@ -9,214 +9,223 @@ using namespace std; int main(int argc, char* argv[]) { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); - return 1; - } - - int numVideoDrivers = SDL_GetNumVideoDrivers(); - if (numVideoDrivers < 1) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no video drivers: %s", SDL_GetError()); - return 1; - } - cout << "Video Drivers:" << endl; - for (int i = 0; i < numVideoDrivers; i++) { - std::cout << i << ". " << SDL_GetVideoDriver(i) << endl; - } - - int numRenderDrivers = SDL_GetNumRenderDrivers(); - if (numRenderDrivers < 1) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no render drivers: %s", SDL_GetError()); - } - cout << "Render Drivers:" << endl; - for (int i = 0; i < numRenderDrivers; i++) { - SDL_RendererInfo ri; - SDL_GetRenderDriverInfo(i, &ri); - std::cout << i << ". " << ri.name << " --- Num Tex fmt: " << ri.num_texture_formats << endl; - } - - int numVideoDisplay = SDL_GetNumVideoDisplays(); - if (numVideoDisplay <= 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no Video displays: %s", SDL_GetError()); - } - cout << "Num Video Displays:" << numVideoDisplay << endl; - for (int i = 0; i < numVideoDisplay; i++) { - int numDisplayModes = SDL_GetNumDisplayModes(i); - if (numDisplayModes < 1) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no display mode: %s", SDL_GetError()); - } - cout << "Display Modes of index " << i << ':' << endl; - for (int j = 0; j < numDisplayModes; j++) { - SDL_DisplayMode dm; - SDL_GetDisplayMode(i, j, &dm); - std::cout << i << "." << j << ". " << dm.w << " x " << dm.h << " Hz: " << dm.refresh_rate << " pxl: " << dm.format << endl; - } - } - - SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LogPriority::SDL_LOG_PRIORITY_DEBUG); - // --- end SDL2 system init and info - VgaTerminal term2 = VgaTerminal("T2 test", 640, 400, 0, -1, 0); - term2.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; - term2.write("events: understand which windows is focused...", 10, 0); - term2.writeXY(10, 1, "**** Viewporting ****", 10, 0); - term2.writeXY(10, 2, "* *", 10, 0); - term2.writeXY(10, 3, "* *", 10, 0); - term2.writeXY(10, 4, "* *", 10, 0); - term2.writeXY(10, 5, "* *", 10, 0); - term2.writeXY(10, 6, "* *", 10, 0); - term2.writeXY(10, 7, "*********************", 10, 0); - - term2.setViewPort(11, 2, 19, 5); - term2.write("Hello ViewPort !!!", 1, 14); - term2.render(); - SDL_Delay(1000); - - VgaTerminal term1 = VgaTerminal("VgaTerminal",720,400, 0, -1, 0); - if (SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2") == SDL_FALSE) { - cerr << "SetHint failed" << endl; - } - - SDL_Event event; - bool quit = false; - - for (int i = 0; i < 256; i++) { - term1.write(static_cast(i), i, 255 - i); - } - - cout << "Keyboards specials on the focused window: " << endl - << "Press F11 to toggle fullscreen" << endl - << "press C to clear" - << "press S to change cursor shape" << endl - << "press + / Keypad + to increase cursor blinking speed" << endl - << "press - / Keypad - to decrease cursor blinkgin speed" << endl - << "[Viewport Window only] up/down/left/right arrows to move the cursor" << endl; - - term1.render(); - SDL_Delay(500); - term1.writeXY(40, 12, "Again!", 9, 15); - term1.render(); - SDL_Delay(500); - term1.writeXY(10, 15, "ÉÍÍÍÍÍÍÍÍÍ»", 14 , 2); - term1.writeXY(10, 16, "º º", 14 , 2); - term1.writeXY(10, 17, "ÈÍÍÍÍÍÍÍÍͼ", 14 , 2); - term1.gotoXY(12, 16); term1.write(3, 4, 15); - term1.gotoXY(14, 16); term1.write(4, 15, 4); - term1.gotoXY(16, 16); term1.write(5, 0, 15); - term1.gotoXY(18, 16); term1.write(6, 15, 0); - term1.render(); - term1.gotoXY(40, 24); - term1.render(); - - Window::handler_t f = [](const SDL_Event& event, Window* w) { - VgaTerminal* term = reinterpret_cast(w); - SDL_UserEvent userevent; - string keyname; - switch (event.type) { - case SDL_KEYDOWN: - keyname = SDL_GetKeyName(event.key.keysym.sym); - if (keyname == "Left") { - term->moveCursorLeft(); - } - else if (keyname == "Right") { - term->moveCursorRight(); - } - else if (keyname == "Up") { - term->moveCursorUp(); - } - else if (keyname == "Down") { - term->moveCursorDown(); - } - break; - case SDL_USEREVENT: - userevent = event.user; - // at some point a better event name should be used - if (userevent.type == SDL_USEREVENT && userevent.code == 0) { - // the commented code below is intended as an example - //std::cout << "cursor event!" << endl; - } - else { - //cout << userevent.code << endl; - } - break; - } - - return true; - }; - - term2.handler = f; - term2.cursor_time = 100; - - string keyname; - while (!quit) { - SDL_WaitEvent(&event); - term2.handleEvent(event); - term1.handleEvent(event); - - VgaTerminal* term; - if (event.window.windowID == term1.getWindowId()) { - term = &term1; - } - else if (event.window.windowID == term2.getWindowId()) { - term = &term2; - } - else { - term1.render(); - term2.render(); - continue; - } - - switch (event.type) { - - case SDL_QUIT: - quit = true; - break; - case SDL_KEYDOWN: - keyname = SDL_GetKeyName(event.key.keysym.sym); - if (keyname == "F11") { - term->toggleFullscreenDesktop(); - term->render(true); - } - break; - case SDL_KEYUP: - /* Print the hardware scancode first */ - printf("Scancode: 0x%02X", event.key.keysym.scancode); - /* Print the name of the key */ - keyname = SDL_GetKeyName(event.key.keysym.sym); - printf(", Name: %s", keyname.c_str()); - cout << endl; - if (keyname == "Escape") { - quit = true; - } - else if (keyname == "C") { - cout << "clearing..." << endl; - term->clear(); - } - else if (keyname == "S") { - cout << "cursor shape..." << endl; - // unsafe cursor rotation, please be a little bit more verbose - // and handle properly the cases. - auto cs = (static_cast(term->cursor_mode) + 1) % VgaTerminal::NUM_CURSOR_MODES; - term->cursor_mode = static_cast(cs); - } - else if ((event.key.keysym.sym == SDLK_EQUALS && event.key.keysym.mod & KMOD_SHIFT) || keyname == "Keypad +") { - term->cursor_time = static_cast(round(term->cursor_time * 0.9)); - cout << "incresing cursor speed (decrease cursor_time) ~10% = " << term->cursor_time << endl; - } - else if ((keyname == "Keypad -") || (keyname == "-")) { - term->cursor_time = static_cast(round(term->cursor_time * 1.1)); - cout << "decresing cursor speed (incresing cursor_time) ~10% = " << term->cursor_time << endl; - } - else { - term->write(keyname, 1, 10); - } - - break; - } - - term1.render(); - term2.render(); - } - - SDL_Quit(); - return 0; + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + + int numVideoDrivers = SDL_GetNumVideoDrivers(); + if (numVideoDrivers < 1) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no video drivers: %s", SDL_GetError()); + return 1; + } + cout << "Video Drivers:" << endl; + for (int i = 0; i < numVideoDrivers; i++) { + std::cout << i << ". " << SDL_GetVideoDriver(i) << endl; + } + + int numRenderDrivers = SDL_GetNumRenderDrivers(); + if (numRenderDrivers < 1) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no render drivers: %s", SDL_GetError()); + } + cout << "Render Drivers:" << endl; + for (int i = 0; i < numRenderDrivers; i++) { + SDL_RendererInfo ri; + SDL_GetRenderDriverInfo(i, &ri); + std::cout << i << ". " << ri.name << " --- Num Tex fmt: " << ri.num_texture_formats << endl; + } + + int numVideoDisplay = SDL_GetNumVideoDisplays(); + if (numVideoDisplay <= 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no Video displays: %s", SDL_GetError()); + } + cout << "Num Video Displays:" << numVideoDisplay << endl; + for (int i = 0; i < numVideoDisplay; i++) { + int numDisplayModes = SDL_GetNumDisplayModes(i); + if (numDisplayModes < 1) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "no display mode: %s", SDL_GetError()); + } + cout << "Display Modes of index " << i << ':' << endl; + for (int j = 0; j < numDisplayModes; j++) { + SDL_DisplayMode dm; + SDL_GetDisplayMode(i, j, &dm); + std::cout << i << "." << j << ". " << dm.w << " x " << dm.h << " Hz: " << dm.refresh_rate << " pxl: " << dm.format << endl; + } + } + + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LogPriority::SDL_LOG_PRIORITY_DEBUG); + // --- end SDL2 system init and info + VgaTerminal term2 = VgaTerminal("T2 test", 640, 400, 0, -1, 0); + term2.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; + term2.write("events: understand which windows is focused...", 10, 0); + term2.writeXY(10, 1, "**** Viewporting ****", 10, 0); + term2.writeXY(10, 2, "* *", 10, 0); + term2.writeXY(10, 3, "* *", 10, 0); + term2.writeXY(10, 4, "* *", 10, 0); + term2.writeXY(10, 5, "* *", 10, 0); + term2.writeXY(10, 6, "* *", 10, 0); + term2.writeXY(10, 7, "*********************", 10, 0); + + term2.setViewPort(11, 2, 19, 5); + term2.write("Hello ViewPort !!!", 1, 14); + term2.render(); + SDL_Delay(1000); + + VgaTerminal term1 = VgaTerminal("VgaTerminal", 720, 400, 0, -1, 0); + if (SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2") == SDL_FALSE) { + cerr << "SetHint failed" << endl; + } + + SDL_Event event; + bool quit = false; + + for (int i = 0; i < 256; i++) { + term1.write(static_cast(i), i, 255 - i); + } + + cout << "Keyboards specials on the focused window: " << endl + << "Press F11 to toggle fullscreen" << endl + << "press C to clear" + << "press S to change cursor shape" << endl + << "press B to toggle blinking cursor" << endl + << "press + / Keypad + to increase cursor blinking speed" << endl + << "press - / Keypad - to decrease cursor blinkgin speed" << endl + << "[Viewport Window only] up/down/left/right arrows to move the cursor" << endl; + + term1.render(); + SDL_Delay(500); + term1.writeXY(40, 12, "Again!", 9, 15); + term1.render(); + SDL_Delay(500); + term1.writeXY(10, 15, "ÉÍÍÍÍÍÍÍÍÍ»", 14, 2); + term1.writeXY(10, 16, "º º", 14, 2); + term1.writeXY(10, 17, "ÈÍÍÍÍÍÍÍÍͼ", 14, 2); + term1.gotoXY(12, 16); + term1.write(3, 4, 15); + term1.gotoXY(14, 16); + term1.write(4, 15, 4); + term1.gotoXY(16, 16); + term1.write(5, 0, 15); + term1.gotoXY(18, 16); + term1.write(6, 15, 0); + term1.render(); + term1.gotoXY(40, 24); + term1.render(); + + Window::handler_t f = [](const SDL_Event& event, Window* w) { + VgaTerminal* term = reinterpret_cast(w); + SDL_UserEvent userevent; + string keyname; + switch (event.type) { + case SDL_KEYDOWN: + keyname = SDL_GetKeyName(event.key.keysym.sym); + if (keyname == "Left") { + term->moveCursorLeft(); + } + else if (keyname == "Right") { + term->moveCursorRight(); + } + else if (keyname == "Up") { + term->moveCursorUp(); + } + else if (keyname == "Down") { + term->moveCursorDown(); + } + break; + case SDL_USEREVENT: + userevent = event.user; + // at some point a better event name should be used + if (userevent.type == SDL_USEREVENT && userevent.code == 0) { + // the commented code below is intended as an example + // std::cout << "cursor event!" << endl; + } + else { + // cout << userevent.code << endl; + } + break; + } + + return true; + }; + + term2.handler = f; + term2.cursor_time = 100; + // term2.setCursorSpeed(VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_FAST); + + string keyname; + while (!quit) { + SDL_WaitEvent(&event); + term2.handleEvent(event); + term1.handleEvent(event); + + VgaTerminal* term; + if (event.window.windowID == term1.getWindowId()) { + term = &term1; + } + else if (event.window.windowID == term2.getWindowId()) { + term = &term2; + } + else { + term1.render(); + term2.render(); + continue; + } + + switch (event.type) { + case SDL_QUIT: + quit = true; + break; + case SDL_KEYDOWN: + keyname = SDL_GetKeyName(event.key.keysym.sym); + if (keyname == "F11") { + term->toggleFullscreenDesktop(); + term->render(true); + } + break; + case SDL_KEYUP: + /* Print the hardware scancode first */ + printf("Scancode: 0x%02X", event.key.keysym.scancode); + /* Print the name of the key */ + keyname = SDL_GetKeyName(event.key.keysym.sym); + printf(", Name: %s", keyname.c_str()); + cout << endl; + if (keyname == "Escape") { + quit = true; + } + else if (keyname == "C") { + cout << "clearing..." << endl; + term->clear(); + } + else if (keyname == "S") { + cout << "cursor shape..." << endl; + // unsafe cursor rotation, please be a little bit more verbose + // and handle properly the cases. + auto cs = (static_cast(term->cursor_mode) + 1) % VgaTerminal::NUM_CURSOR_MODES; + term->cursor_mode = static_cast(cs); + } + else if (keyname == "B") { + cout << "toggle cursor blinking..." << endl; + term->blinkCursor = !term->blinkCursor; + } + else if ((event.key.keysym.sym == SDLK_EQUALS && event.key.keysym.mod & KMOD_SHIFT) || keyname == "Keypad +") { + term->cursor_time = static_cast(round(term->cursor_time * 0.9)); + cout << "incresing cursor speed (decrease cursor_time) ~10% = " << term->cursor_time << endl; + } + else if ((keyname == "Keypad -") || (keyname == "-")) { + term->cursor_time = static_cast(round(term->cursor_time * 1.1)); + cout << "decresing cursor speed (incresing cursor_time) ~10% = " << term->cursor_time << endl; + } + else { + term->write(keyname, 1, 10); + } + + break; + } + + term1.render(); + term2.render(); + } + + SDL_Quit(); + return 0; } diff --git a/sdl2-vga-terminal/include/vga-terminal.h b/sdl2-vga-terminal/include/vga-terminal.h index a1534ab3..b09d046b 100644 --- a/sdl2-vga-terminal/include/vga-terminal.h +++ b/sdl2-vga-terminal/include/vga-terminal.h @@ -11,16 +11,16 @@ #ifdef __cplusplus extern "C" { #endif - typedef void VGA_Terminal; - VGA_TERMINAL_EXPORT const char* VGA_TERMINAL_version(); - /// create a new terminal, SDL_INIT VIDEO & TIMER must be inited first. - VGA_TERMINAL_EXPORT VGA_Terminal* VGA_TERMINAL_init(); - /// destroy the given terminal - VGA_TERMINAL_EXPORT void VGA_TERMINAL_destroy(VGA_Terminal* term); - /// write in the terminal - VGA_TERMINAL_EXPORT void VGA_TERMINAL_writeXY(VGA_Terminal* term, const uint8_t x, const uint8_t y, const char* str, const uint8_t col, const uint8_t bgCol); - /// render in the terminal - VGA_TERMINAL_EXPORT void VGA_TERMINAL_render(VGA_Terminal* term); +typedef void VGA_Terminal; +VGA_TERMINAL_EXPORT const char* VGA_TERMINAL_version(); +/// create a new terminal, SDL_INIT VIDEO & TIMER must be inited first. +VGA_TERMINAL_EXPORT VGA_Terminal* VGA_TERMINAL_init(); +/// destroy the given terminal +VGA_TERMINAL_EXPORT void VGA_TERMINAL_destroy(VGA_Terminal* term); +/// write in the terminal +VGA_TERMINAL_EXPORT void VGA_TERMINAL_writeXY(VGA_Terminal* term, const uint8_t x, const uint8_t y, const char* str, const uint8_t col, const uint8_t bgCol); +/// render in the terminal +VGA_TERMINAL_EXPORT void VGA_TERMINAL_render(VGA_Terminal* term); #ifdef __cplusplus } #endif diff --git a/sdl2-vga-terminal/src/TuiTerminal.cpp b/sdl2-vga-terminal/src/TuiTerminal.cpp new file mode 100644 index 00000000..34dc5279 --- /dev/null +++ b/sdl2-vga-terminal/src/TuiTerminal.cpp @@ -0,0 +1,360 @@ +#include "TuiTerminal.hpp" +#include +#include "tui/utils.hpp" + + +TuiTerminal::TuiTerminal(const std::string& title, const std::string& description) : + _term(VgaTerminal(title)), _title(title), _desc(description) +{ + _term.autoScroll = false; + _term.showCursor = false; +} + +SDL_Window* TuiTerminal::getWindow() +{ + return _term.getWindow(); +} + +SDL_Renderer* TuiTerminal::getRenderer() +{ + return _term.getRenderer(); +} + +void TuiTerminal::draw() +{ + _term.resetViewport(); + _drawBackGround(); + _drawHeader(); + _drawFooter(); + _term.setViewPort(0, 5, _term.getMode().tw, _term.getMode().th - 5); +} + +void TuiTerminal::render(const bool force) +{ + _term.render(force); +} + +void TuiTerminal::_drawBackGround() noexcept +{ + _term.fill(background_tc.c, background_tc.col, background_tc.bgCol); +} + +void TuiTerminal::_drawHeader() +{ + constexpr uint8_t x = 4; + constexpr uint8_t y = 0; + constexpr uint8_t w = 72; + constexpr uint8_t h = 3; + constexpr uint8_t col = 14; + constexpr uint8_t bgCol = 1; + constexpr SDL_Rect r{ x, y, w, h }; + + const std::string version = std::string("Version ") + VERSION; + auto [lmark, rmark] = tui::align3Strings(_title, _desc, version, w); + const SDL_Rect rl = { x, y, lmark, h }; + const SDL_Rect rm = { x+lmark-1, y, rmark-lmark+1, h }; + const SDL_Rect rr = { x+rmark-1, y, w-rmark+1, h }; + + _drawLeftBorder(rl, col, bgCol, _title); + _drawMiddleBorder(rm, col, bgCol, _desc); + _drawRightBorder(rr, col, bgCol, version); + _drawShadow(r); +} + +void TuiTerminal::drawSingleBorderDialog(const SDL_Rect& r, uint8_t col, uint8_t bgCol, const std::string& title, const std::string& body) +{ + if (r.h < 3) { + throw std::invalid_argument("height must be 3 at least"); + } + + if (r.w < title.size() + 2) { + throw std::invalid_argument("title too long"); + } + + if (r.w < body.size() + 2) { + throw std::invalid_argument("body too long"); + } + + + std::string padTitle = tui::alignString(title, static_cast(r.w - 2 - title.size()), 196); + std::string padBody = tui::alignString(body, static_cast(r.w - 2 - body.size()), ' '); + // Top + _term.gotoXY(static_cast(r.x), static_cast(r.y)); + _term.write(218, col, bgCol); + _term.write(padTitle, col, bgCol); + _term.write(191, col, bgCol); + // Middle + _term.gotoXY(static_cast(r.x), static_cast(r.y + 1)); + _term.write(179, col, bgCol); + _term.write(padBody, col, bgCol); + _term.write(179, col, bgCol); + for (int i = 2; i < r.h - 1; i++) + { + _term.gotoXY(static_cast(r.x), static_cast(r.y + i)); + _term.write(179, col, bgCol); + for (int j = 2; j < r.w; j++) { + _term.write(' ', col, bgCol); + } + _term.write(179, col, bgCol); + } + // Bottom + _term.gotoXY(static_cast(r.x), static_cast(r.y + r.h - 1)); + _term.write(192, col, bgCol); + _drawHBorder(static_cast(r.x + 1), static_cast(r.y + r.h - 1), static_cast(r.w), col, bgCol, 196); + _term.write(217, col, bgCol); + _drawShadow(r); +} + +void TuiTerminal::drawDialog(const SDL_Rect& r, uint8_t col, uint8_t bgCol, const std::string& header, const std::string& body) +{ + if (r.h < 5) { + throw std::invalid_argument("height must be 3 at least"); + } + + if (r.w < header.size() - 2) { + throw std::invalid_argument("title too long"); + } + + if (r.w < body.size() - 2) { + throw std::invalid_argument("body too long"); + } + + std::string padTitle = tui::alignString(header, static_cast(r.w - 2 - header.size()), 196); + std::string padBody = tui::alignString(body, static_cast(r.w - 2 - body.size()), ' '); + + // Header + // Top + _term.gotoXY(static_cast(r.x), static_cast(r.y)); + _term.write(218, col, bgCol); + _term.write(padTitle, col, bgCol); + _term.write(183, col, bgCol); + // Middle + _term.gotoXY(static_cast(r.x), static_cast(r.y + 1)); + _term.write(179, col, bgCol); + _term.write(padBody, col, bgCol); + _term.write(186, col, bgCol); + // Bottom + _term.gotoXY(static_cast(r.x), static_cast(r.y + 2)); + _term.write(195, col, bgCol); + _drawHBorder(static_cast(r.x + 1), static_cast(r.y + 2), static_cast(r.w), col, bgCol, 196); + _term.write(182, col, bgCol); + // End Header + + // Body + for (int i = 3; i < r.h - 1; i++) + { + _term.gotoXY(static_cast(r.x), static_cast(r.y + i)); + _term.write(179, col, bgCol); + for (int j = 2; j < r.w; j++) { + _term.write(' ', col, bgCol); + } + _term.write(186, col, bgCol); + } + // Bottom + _term.gotoXY(static_cast(r.x), static_cast(r.y + r.h - 1)); + _term.write(212, col, bgCol); + _drawHBorder(static_cast(r.x + 1), static_cast(r.y + r.h - 1), static_cast(r.w), col, bgCol, 205); + _term.write(188, col, bgCol); + _drawShadow(r); +} + +// progress [0, max] +void TuiTerminal::progressBar(const bool colored, const bool showProgress, const uint8_t x, const uint8_t y, const uint8_t width, const size_t progress, const size_t max) +{ + // TODO progressBar algorithm is not optimal + // BODY there are wasting operations in + // BODY drawing the same cell each call. + // BODY + // BODY --- + // BODY + // BODY - clear the line should not required. + // BODY - if not colored, just check if need to fill the "next cell" + // BODY - if colored redraw only when there is a change in color from previous call. + // BODY - rewrite always the showProgress (promote to a label and here generate an event?) + // ----------------- + + // red until 33% + // yellow until 67% + // green until 100% + + // TODO as parameter, + // BODY ... from parent container.. + constexpr uint8_t _col = 15; + constexpr uint8_t bgCol = 1; + constexpr int bufSize = 5; + uint8_t _length; + + // width > bufsize if colored && _length >= 3 + if (showProgress) { + _length = width - bufSize; + } + else { + _length = width; + } + + // this is sub-optimal, it is drawing twice, can be done exactly once + _drawHBorder(x, y, width, _col, bgCol, ' '); + _term.gotoXY(x, y); + // X = X:length = progress:max => x*max/100 = progress => X = progress*100/max + const double ratio = progress / static_cast(max); + const uint8_t cur = static_cast(abs(ratio * _length)); + + uint8_t col; + if (colored) { + // determing color + if (ratio < 0.33) { + //red + uint8_t rest = static_cast(abs((ratio) * 10.0)); + col = 0x27 + rest; + // 0.67 - 0.33 = 0.34 (0.33) + } + else if (ratio < 0.67) { + // yellow + uint8_t rest = static_cast(abs((ratio - 0.33) * 10.0)); + col = 0x2A + rest; + } + else { + // green + uint8_t rest = static_cast(abs((ratio - 0.67) * 10.0)); + col = 0x2D + rest; + } + } + else { + col = _col; + } + + for (int i = 0; i < cur; i++) { + _term.write(219, col, bgCol); + } + for (int i = cur; i < _length; i++) { + _term.write(176, _col, bgCol); + } + + if (showProgress) { + char buf[bufSize]; + + snprintf(buf, bufSize, "%3.0f%%", 100.0 * ratio); + _term.writeXY(x + _length + 1, y, buf, _col, bgCol); + } +} + + +void TuiTerminal::_drawBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str, const uint8_t tc, const uint8_t mc, const uint8_t bc) +{ + if (r.h < 3) { + throw std::invalid_argument("height must be 3 at least"); + } + + // Top + _term.gotoXY(static_cast(r.x), static_cast(r.y)); + _term.write(tc, col, bgCol); + _drawHBorder(static_cast(r.x + 1), static_cast(r.y), static_cast(r.w), col, bgCol, 205); + // Middle + for (uint8_t i = 1; i < r.h - 1; i++) { + _term.gotoXY(static_cast(r.x), static_cast(r.y + i)); + _term.write(mc, col, bgCol); + } + + // at the moment only on the 2nd row other are just "padding" + _term.writeXY(static_cast(r.x + 1), static_cast(r.y + 1), + tui::alignString(str, static_cast(r.w - 2 - str.size()), ' '), col, bgCol); + + // Bottom + _term.gotoXY(static_cast(r.x), static_cast(r.y + r.h - 1)); + _term.write(bc, col, bgCol); + _drawHBorder(static_cast(r.x + 1), static_cast(r.y + r.h - 1), static_cast(r.w), col, bgCol, 205); +} + +void TuiTerminal::_drawLeftBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str) +{ + _drawBorder(r, col, bgCol, str, 201, 186, 200); +} + +void TuiTerminal::_drawMiddleBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str) +{ + _drawBorder(r, col, bgCol, str, 209, 179, 207); +} + +void TuiTerminal::_drawRightBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str) +{ + _drawMiddleBorder(r, col, bgCol, str); + + uint8_t xw = static_cast(r.x + r.w - 1); + _term.gotoXY(xw, static_cast(r.y)); + _term.write(187, col, bgCol); + for (uint8_t i = 1; i < r.h - 1; i++) { + _term.gotoXY(xw, static_cast(r.y + i)); + _term.write(186, col, bgCol); + } + _term.gotoXY(xw, static_cast(r.y + r.h - 1)); + _term.write(188, col, bgCol); +} + +void TuiTerminal::_drawHBorder(const uint8_t x, const uint8_t y, const uint8_t width, const uint8_t col, const uint8_t bgCol, const uint8_t c) noexcept +{ + _term.gotoXY(x, y); + for (uint8_t i = 2; i < width; i++) { + _term.write(c, col, bgCol); + } +} + +void TuiTerminal::_unitShadowColor(uint8_t& col) +{ + if (col < 8) { + col = 0; + } + else if (col < 16) { + // in the 16 colors range + col &= 0x7; + } + else if (col < 24) { + // dark gray scale + col = 16; + } + else if (col < 32) { + col -= 8; + } + else if (col < 104) { + // light color + col += 103; + } + else { + // dark color + // didn't exploit a mapping + col = 0; + } +} + +void TuiTerminal::_shadowColor(VgaTerminal::terminalChar_t& tc) +{ + _unitShadowColor(tc.col); + _unitShadowColor(tc.bgCol); +} + +void TuiTerminal::_drawShadow(const SDL_Rect& r) noexcept +{ + _term.gotoXY(static_cast(r.x + 2), static_cast(r.y + r.h)); + for (int i = 0; i < r.w; i++) { + auto tc = _term.at(_term.getX(), _term.getY()); + _shadowColor(tc); + _term.write(tc); + } + + for (int i = 1; i < r.h; i++) { + _term.gotoXY(static_cast(r.x + r.w), static_cast(r.y + i)); + for (int j = 0; j < 2; j++) { + auto tc = _term.at(_term.getX(), _term.getY()); + _shadowColor(tc); + _term.write(tc); + } + } +} + +void TuiTerminal::_drawFooter() noexcept +{ + _term.writeXY(0, 24, " D", 4, 15); + _term.write("OS TUI Emulation...", 0, 15); + for (int i = _term.getX(); i < _term.getMode().tw; i++) { + _term.write(footer_tc.c, footer_tc.col, footer_tc.bgCol); + } +} diff --git a/sdl2-vga-terminal/src/TuiTerminal.hpp b/sdl2-vga-terminal/src/TuiTerminal.hpp new file mode 100644 index 00000000..a2ce325d --- /dev/null +++ b/sdl2-vga-terminal/src/TuiTerminal.hpp @@ -0,0 +1,70 @@ +/************************************************************* + *** Text User Interface utilities *** + *** ===================================================== *** + *** Some basic TUI components *** + *** if growing, to be promoted as a stand-alone library *** + *** or could be just a component of this library *** + *** ----------------------------------------------------- *** + *** Description: *** + *** using VgaTerminal in mode3 *** + *** - no other method allowed *** + *** - no access to VgaTerminal *** + *** - no access to Window *** + *** - working with default palette colors only *** + *** - Header display a title, description and TUI Version *** + *** - background *** + *** - fix Footer *** + *** - no access to Window or VgaTerminal *** + *** ===================================================== *** + *** VERSION 0.1-showcase *** + *************************************************************/ +#pragma once + + +#include "VgaTerminal.hpp" +#include + + +class TuiTerminal +{ +public: + static constexpr const char* VERSION = "0.1"; + + TuiTerminal(const std::string& title, const std::string& description); + // TODO wrappers to getWindow and renderer + // BODY I don't like this desing... refactor with an interface + SDL_Window* getWindow(); + SDL_Renderer* getRenderer(); + void draw(); + void render(const bool force = false); + VgaTerminal::terminalChar_t background_tc = { 177, 8, 9 }; + VgaTerminal::terminalChar_t footer_tc = { 219, 15, 1}; + static constexpr uint8_t defaultCol = 15; + static constexpr uint8_t defaultBgCol = 1; + // TODO use a label object (component interface) for the body + void drawSingleBorderDialog(const SDL_Rect& r, uint8_t col, uint8_t bgCol, const std::string& title, const std::string& body); + void drawDialog(const SDL_Rect& r, uint8_t col, uint8_t bgCol, const std::string& header, const std::string& body); + // progress bar, todo as a component + void progressBar(const bool colored, const bool showProgress, const uint8_t x, const uint8_t y, const uint8_t width, const size_t progress, const size_t max); +protected: +private: + VgaTerminal _term; + const std::string _title; + const std::string _desc; + + void _drawBackGround() noexcept; + void _drawHeader(); + // helpers functions + void _drawBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str, const uint8_t tc, const uint8_t mc, const uint8_t bc); + void _drawLeftBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str); + void _drawMiddleBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str); + void _drawRightBorder(const SDL_Rect& r, const uint8_t col, const uint8_t bgCol, const std::string& str); + void _drawHBorder(const uint8_t x, const uint8_t y, const uint8_t width, const uint8_t col, const uint8_t bgCol, const uint8_t c) noexcept; + // ----- + // Shadow methods (split?) + void _unitShadowColor(uint8_t& col); + void _shadowColor(VgaTerminal::terminalChar_t& tc); + void _drawShadow(const SDL_Rect& r) noexcept; + // footer + void _drawFooter() noexcept; +}; diff --git a/sdl2-vga-terminal/src/VgaTerminal.cpp b/sdl2-vga-terminal/src/VgaTerminal.cpp index 429da21e..0ac1a0c5 100644 --- a/sdl2-vga-terminal/src/VgaTerminal.cpp +++ b/sdl2-vga-terminal/src/VgaTerminal.cpp @@ -1,32 +1,37 @@ #include "VgaTerminal.hpp" #include -#include #include "vgafonts.h" #include "vgapalette.h" #include +#include +#include "exceptions/exceptions.hpp" +#include -template -constexpr auto RESIZE_VGA_PALETTE(T x) { return (x * 255 / 0x3F); } +template +constexpr auto RESIZE_VGA_PALETTE(T x) { + return (x * 255 / 0x3F); +} + const VgaTerminal::videoMode_t VgaTerminal::mode3 = { - static_cast (0x003), // mode - static_cast (80), // tw - static_cast (25), // th - static_cast (8), // cw - static_cast (VGA_FONT_SIZE_16), // ch - PALETTE_3_COLORS, - vgafont16, - palette3, - vgafont_cursors16, + static_cast (0x003), // mode + static_cast (80), // tw + static_cast (25), // th + static_cast (8), // cw + static_cast (VGA_FONT_SIZE_16), // ch + PALETTE_3_COLORS, + vgafont16, + palette3, + vgafont_cursors16, }; bool VgaTerminal::_terminalChar_t::operator==(const _terminalChar_t& o) const { return rendered == o.rendered - && c == o.c - && col == o.col - && bgCol == o.bgCol; + && c == o.c + && col == o.col + && bgCol == o.bgCol; } const std::string VgaTerminal::getVersion() @@ -41,24 +46,29 @@ VgaTerminal::~VgaTerminal() } } -VgaTerminal::VgaTerminal(const std::string &title, const int winFlags, const int drvIndex, const int renFlags) : +VgaTerminal::VgaTerminal(const std::string& title) : + VgaTerminal(title, 0, -1, 0) +{ +} + +VgaTerminal::VgaTerminal(const std::string& title, const int winFlags, const int drvIndex, const int renFlags) : VgaTerminal(title, mode3.tw * mode3.cw, mode3.th * mode3.ch, winFlags, drvIndex, renFlags) { } -VgaTerminal::VgaTerminal(const std::string &title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags) +VgaTerminal::VgaTerminal(const std::string& title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags) : VgaTerminal(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, winFlags, drvIndex, renFlags) { } VgaTerminal::VgaTerminal(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags) : Window(title, x, y, width, height, winFlags, drvIndex, renFlags), - mode(mode3) + mode(mode3) { resetViewport(); if (SDL_RenderSetLogicalSize(getRenderer(), mode.tw * mode.cw, mode.th * mode.ch) < 0) { - throw std::runtime_error(std::string("unable to set logical rendering. Error: ") + SDL_GetError()); + throw exceptions::LogicalRenderError(std::string("unable to set logical rendering. Error: ") + SDL_GetError()); } _pal.ncolors = mode.numColors; @@ -78,7 +88,7 @@ VgaTerminal::VgaTerminal(const std::string& title, const int x, const int y, con _cursorTimerId = SDL_AddTimer(cursor_time, _timerCallBackWrapper, this); if (_cursorTimerId == 0) { SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "[%s] %s: unable to add cursor callback. Error: %s", - typeid(*this).name(), __func__, SDL_GetError()); + typeid(*this).name(), __func__, SDL_GetError()); } } else { @@ -100,9 +110,9 @@ void VgaTerminal::_renderFontChar(const SDL_Point& dst, _terminalChar_t& tc) void VgaTerminal::_renderCharLine(const std::bitset<8>& line, const int dstx, const int dsty, const uint8_t col, const uint8_t bgCol) { - // lsz is mode.cw, - // start make sense spliting to a VgaTerminalRender, all the - // rendering functions. + // TODO lsz is mode.cw, + // BODY start make sense spliting to a VgaTerminalRender, all the + // BODY rendering functions. constexpr auto lsz = 8; SDL_Point points[lsz]; uint8_t fgi = 0; @@ -113,19 +123,16 @@ void VgaTerminal::_renderCharLine(const std::bitset<8>& line, const int dstx, co else points[--bgi] = { dstx - x, dsty }; } - SDL_SetRenderDrawColor(getRenderer(), _pal.colors[col].r, _pal.colors[col].g, _pal.colors[col].b, _pal.colors[col].a); - SDL_RenderDrawPoints(getRenderer(), points, fgi); - SDL_SetRenderDrawColor(getRenderer(), _pal.colors[bgCol].r, _pal.colors[bgCol].g, _pal.colors[bgCol].b, _pal.colors[bgCol].a); - SDL_RenderDrawPoints(getRenderer(), &points[fgi], lsz - bgi); + renderDrawPoints(_pal.colors[col], points, fgi); + renderDrawPoints(_pal.colors[bgCol], &points[fgi], lsz - bgi); } void VgaTerminal::_renderCursor(const SDL_Point& dst, const _terminalChar_t& tc) { - const uint8_t col = tc.col == tc.bgCol ? + const uint8_t col = tc.col == tc.bgCol ? cursorDefaultCol : - tc.col - ; - + tc.col; + const int dstx = dst.x + mode.cw; const uint8_t* font = &mode.font[static_cast(tc.c) * mode.ch]; const uint8_t* cursorFont = &mode.cursors[static_cast(cursor_mode) * mode.ch]; @@ -168,16 +175,23 @@ uint8_t VgaTerminal::getY() const noexcept void VgaTerminal::write(const uint8_t c, const uint8_t col, const uint8_t bgCol) noexcept { _terminalChar_t tc; - tc.bgCol = bgCol; tc.c = c; tc.col = col; tc.rendered = false; - _setCursorChar(tc); + tc.bgCol = bgCol; + tc.c = c; + tc.col = col; + tc.rendered = false; + _setCharAtCursorPosition(tc); _incrementCursorPosition(); } +void VgaTerminal::write(const terminalChar_t tc) noexcept +{ + write(tc.c, tc.col, tc.bgCol); +} + void VgaTerminal::write(const std::string &str, const uint8_t col, const uint8_t bgCol) noexcept { - size_t sz = str.size(); - for (size_t i = 0; i < sz; i++) { - write(str[i], col, bgCol); + for (const char c : str) { + write(c, col, bgCol); } } @@ -188,10 +202,10 @@ void VgaTerminal::writeXY(const uint8_t x, const uint8_t y, const std::string &s } /** - * @brief - * - * @param x - * @param y + * @brief + * + * @param x + * @param y * @return VgaTerminal::terminalChar_t defaultNullChar if out of screen */ VgaTerminal::terminalChar_t VgaTerminal::at(const uint8_t x, const uint8_t y) noexcept @@ -199,19 +213,21 @@ VgaTerminal::terminalChar_t VgaTerminal::at(const uint8_t x, const uint8_t y) no if (x >= _viewPortWidth || y >= _viewPortHeight) { return _defaultNullChar; } - + _terminalChar_t _tc = _getCharAt((static_cast(y) + _viewPortY) * mode.tw + x + _viewPortX); terminalChar_t tc; - tc.c = _tc.c; tc.col = _tc.col; tc.bgCol = _tc.bgCol; - + tc.c = _tc.c; + tc.col = _tc.col; + tc.bgCol = _tc.bgCol; + return tc; } void VgaTerminal::_renderGridPartialY(const uint8_t y1, const uint8_t y2, const bool force) { for (int j = y1, j2= y1 * mode.tw, jch = y1 * mode.ch; - j < y2; - j++, j2 += mode.tw, jch += mode.ch) { + j < y2; + j++, j2 += mode.tw, jch += mode.ch) { _renderGridLinePartialX(0, mode.tw, j2, jch, force); } } @@ -220,7 +236,7 @@ void VgaTerminal::_renderGridLinePartialX(const uint8_t x1, const uint8_t x2, co { for (int i = x1, i2 = yw + x1; i < x2; i++, i2++) { _terminalChar_t tc = _getCharAt(i2); - + if (!force && tc.rendered) { continue; } @@ -242,14 +258,14 @@ void VgaTerminal::render(const bool force) int ych = curY * mode.ch; SDL_Point p = { curX * mode.cw, ych }; _terminalChar_t tc = _getCursorChar(); - + std::lock_guard lck(_renderMutex); // top cursor grid _renderGridPartialY(0, curY, force); // left cursor grid _renderGridLinePartialX(0, curX, yw, ych, force); if ((force || !tc.rendered) - && (showCursor && (!_onIdle || _drawCursor))) { + && (showCursor && (!_onIdle || _drawCursor))) { _renderCursor(p, tc); } else { @@ -257,7 +273,7 @@ void VgaTerminal::render(const bool force) } // right cursor grid _renderGridLinePartialX(curX + 1, mode.tw, yw, ych, force); - // bottom cursor grid + // bottom cursor grid _renderGridPartialY(curY + 1, mode.th, force); renderPresent(); @@ -281,7 +297,7 @@ void VgaTerminal::moveCursorLeft() noexcept if (_curX > _viewPortX) { --_curX; } - else if(_curY > _viewPortY) { + else if (_curY > _viewPortY) { --_curY; _curX = _viewPortX2 - 1; } @@ -312,7 +328,7 @@ void VgaTerminal::moveCursorDown() noexcept if (_curY < _viewPortY2 - 1) { ++_curY; } - + _setBusy(); } @@ -361,16 +377,15 @@ bool VgaTerminal::setViewPort(const SDL_Rect& r) noexcept { return setViewPort( static_cast(r.x), - static_cast(r.y), + static_cast(r.y), static_cast(r.w), - static_cast(r.h) - ); + static_cast(r.h)); } SDL_Rect VgaTerminal::getViewport() const noexcept { SDL_Rect r; - + r.x = _viewPortX; r.y = _viewPortY; r.w = _viewPortWidth; @@ -400,28 +415,31 @@ uint32_t VgaTerminal::_timerCallBack(uint32_t interval) { // @TODO review the user event // @BODY at the moment is just using `SDL_USEREVENT`, should be something more specific and unique. - SDL_Event event; - SDL_UserEvent userevent; - - if (_onIdle) { - _drawCursor = !_drawCursor; - } - else { - _onIdle = true; - _drawCursor = true; - } - - _setCursorNotRendered(); + if (showCursor && blinkCursor) { + SDL_Event event; + SDL_UserEvent userevent; - interval = cursor_time; - - userevent.code = 0; - userevent.data1 = userevent.data2 = nullptr; - event.type = userevent.type = SDL_USEREVENT; - event.user = userevent; - userevent.windowID = event.window.windowID = getWindowId(); + if (_onIdle) { + _drawCursor = !_drawCursor; + } + else { + _onIdle = true; + _drawCursor = true; + } + + _setCursorNotRendered(); + + interval = cursor_time; + + userevent.code = 0; + userevent.data1 = userevent.data2 = nullptr; + event.type = userevent.type = SDL_USEREVENT; + event.user = userevent; + userevent.windowID = event.window.windowID = getWindowId(); + + SDL_PushEvent(&event); + } - SDL_PushEvent(&event); return interval; } @@ -452,7 +470,7 @@ void VgaTerminal::_scrollDownGrid() noexcept { int j2 = j * mode.tw; int jj2 = j2 - mode.tw; - + for (int i = _viewPortX; i < _viewPortX2; i++) { int i2 = i + j2; @@ -461,19 +479,48 @@ void VgaTerminal::_scrollDownGrid() noexcept if (_pGrid[i2].rendered && _pGrid[i2] == _pGrid[ii2]) { continue; } - + _pGrid[ii2] = _pGrid[i2]; _pGrid[ii2].rendered = false; } } - - // clear line -> TODO: promote to a public method? - int j2 = (_viewPortY2 - 1) * mode.tw + _viewPortX; + // kept because of mutex. + const int j2 = (_viewPortY2 - 1) * mode.tw + _viewPortX; for (int i = 0; i < _viewPortWidth; i++) { _pGrid[static_cast(i) + j2] = _defaultNullChar; } } +void VgaTerminal::clearLine(const uint8_t y, const uint8_t bgCol) noexcept +{ + if (y >= _viewPortHeight) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "[%s] %s: y outside viewport", typeid(*this).name(), __func__); + return; + } + + const _terminalChar_t tc = { 0, 0, bgCol, false }; + const int j2 = (y + _viewPortY) * mode.tw + _viewPortX; + + std::lock_guard lck(_pGridMutex); + for (int i = 0; i < _viewPortWidth; i++) { + _pGrid[static_cast(i) + j2] = tc; + } +} + +void VgaTerminal::fill(const uint8_t c, const uint8_t col, const uint8_t bgCol) noexcept +{ + gotoXY(0, 0); + const bool old = autoScroll; + autoScroll = false; + for (int j = 0; j < _viewPortHeight; j++) { + for (int i = 0; i < _viewPortWidth; i++) { + write(c, col, bgCol); + } + } + gotoXY(0, 0); + autoScroll = old; +} + const VgaTerminal::videoMode_t VgaTerminal::getMode() const noexcept { return mode; @@ -483,6 +530,17 @@ bool VgaTerminal::isIdle() const noexcept return _onIdle; } +void VgaTerminal::setCursorSpeed(const CURSOR_SPEED speed) noexcept +{ + _cursor_speed = speed; + cursor_time = static_cast(_cursor_speed); +} + +VgaTerminal::CURSOR_SPEED VgaTerminal::getCursorSpeed() const noexcept +{ + return _cursor_speed; +} + VgaTerminal::_terminalChar_t VgaTerminal::_getCharAt(const size_t pos) noexcept { std::lock_guard lck(_pGridMutex); @@ -491,7 +549,7 @@ VgaTerminal::_terminalChar_t VgaTerminal::_getCharAt(const size_t pos) noexcept const int VgaTerminal::_getCursorPosition() const noexcept { - return _curX + _curY * mode.tw; + return _curX + _curY * mode.tw; } VgaTerminal::_terminalChar_t VgaTerminal::_getCursorChar() noexcept @@ -499,7 +557,7 @@ VgaTerminal::_terminalChar_t VgaTerminal::_getCursorChar() noexcept return _getCharAt(_getCursorPosition()); } -void VgaTerminal::_setCursorChar(const _terminalChar_t& tc) noexcept +void VgaTerminal::_setCharAtCursorPosition(const _terminalChar_t& tc) noexcept { std::lock_guard lck(_pGridMutex); _pGrid[_getCursorPosition()] = tc; diff --git a/sdl2-vga-terminal/src/VgaTerminal.hpp b/sdl2-vga-terminal/src/VgaTerminal.hpp index 9100453d..c0b851ba 100644 --- a/sdl2-vga-terminal/src/VgaTerminal.hpp +++ b/sdl2-vga-terminal/src/VgaTerminal.hpp @@ -1,8 +1,5 @@ #pragma once -//#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_FULL_VER < 190023918) -//# error "Visual Studio 2015 Update 2 at least is required" -//#endif #include "Window.hpp" #include @@ -10,6 +7,7 @@ #include #include #include +#include class VgaTerminal : public Window @@ -44,9 +42,15 @@ class VgaTerminal : public Window CURSOR_MODE_VERTICAL = 3, }; static constexpr uint8_t NUM_CURSOR_MODES = 4; - CURSOR_MODE cursor_mode = CURSOR_MODE::CURSOR_MODE_NORMAL; + enum class CURSOR_SPEED : uint16_t { + CURSOR_SPEED_NORMAL = 500, + CURSOR_SPEED_FAST = 250, + CURSOR_SPEED_SLOW = 750 + }; + static constexpr uint8_t NUM_CURSOR_SPEEDS = 3; + static const std::string getVersion(); VgaTerminal() = delete; @@ -54,26 +58,30 @@ class VgaTerminal : public Window VgaTerminal(const VgaTerminal&&) = delete; VgaTerminal& operator=(const VgaTerminal&) = delete; VgaTerminal& operator=(const VgaTerminal&&) = delete; - VgaTerminal(const std::string &title, const int winFlags, const int drvIndex, const int renFlags); - VgaTerminal(const std::string &title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); - VgaTerminal(const std::string &title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); + explicit VgaTerminal(const std::string& title); + VgaTerminal(const std::string& title, const int winFlags, const int drvIndex, const int renFlags); + VgaTerminal(const std::string& title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); + VgaTerminal(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); virtual ~VgaTerminal(); void gotoXY(const uint8_t x, const uint8_t y) noexcept; void gotoXY(const position_t &position) noexcept; - + position_t getXY() const noexcept; uint8_t getX() const noexcept; uint8_t getY() const noexcept; - + void write(const uint8_t c, const uint8_t col, const uint8_t bgCol) noexcept; + void write(const terminalChar_t tc) noexcept; void write(const std::string &str, const uint8_t col, const uint8_t bgCol) noexcept; void writeXY(const uint8_t x, const uint8_t y, const std::string &str, const uint8_t col, const uint8_t bgCol) noexcept; terminalChar_t at(const uint8_t x, const uint8_t y) noexcept; void render(const bool force = false); void clear() noexcept; - + void clearLine(const uint8_t y, const uint8_t bgCol = 0) noexcept; + void fill(const uint8_t c, const uint8_t col, const uint8_t bgCol) noexcept; + void moveCursorLeft() noexcept; void moveCursorRight() noexcept; void moveCursorUp() noexcept; @@ -89,13 +97,18 @@ class VgaTerminal : public Window const videoMode_t getMode() const noexcept; bool isIdle() const noexcept; - + + // NOTE: if you are using the methods do not use cursor_time field. + void setCursorSpeed(const CURSOR_SPEED speed) noexcept; + CURSOR_SPEED getCursorSpeed() const noexcept; + // TODO not really sure what is this for anymore... uint8_t cursorDefaultCol = 7; - std::atomic cursor_time = 500; /// ms + // @deprecated to be removed in 1 + std::atomic cursor_time = static_cast(CURSOR_SPEED::CURSOR_SPEED_NORMAL); /// ms bool showCursor = true; + bool blinkCursor = true; bool autoScroll = true; protected: - private: typedef struct _terminalChar_t : terminalChar_t { @@ -113,7 +126,7 @@ class VgaTerminal : public Window std::mutex _pGridMutex; const _terminalChar_t _defaultNullChar = _terminalChar_t({ 0, 0, 0, false }); std::mutex _renderMutex; - + std::atomic _curX = 0; std::atomic _curY = 0; std::atomic _viewPortX; @@ -122,8 +135,10 @@ class VgaTerminal : public Window std::atomic _viewPortHeight; std::atomic _viewPortX2; /// _viewportX + _viewportWidth derived value std::atomic _viewPortY2; /// _viewportY + _viewportHeight derived value - - std::atomic _drawCursor = true; + + CURSOR_SPEED _cursor_speed = CURSOR_SPEED::CURSOR_SPEED_NORMAL; + //std::atomic _cursor_time = static_cast(_cursor_speed); /// ms + std::atomic _drawCursor = true; SDL_TimerID _cursorTimerId = 0; std::atomic _onIdle = true; void _setBusy() noexcept; @@ -140,6 +155,6 @@ class VgaTerminal : public Window _terminalChar_t _getCharAt(const size_t pos) noexcept; const int _getCursorPosition() const noexcept; _terminalChar_t _getCursorChar() noexcept; - void _setCursorChar(const _terminalChar_t& tc) noexcept; + void _setCharAtCursorPosition(const _terminalChar_t& tc) noexcept; void _setCursorNotRendered() noexcept; }; diff --git a/sdl2-vga-terminal/src/Window.cpp b/sdl2-vga-terminal/src/Window.cpp index aa2e4be3..bc041a01 100644 --- a/sdl2-vga-terminal/src/Window.cpp +++ b/sdl2-vga-terminal/src/Window.cpp @@ -1,97 +1,103 @@ #include "Window.hpp" -#include +#include "exceptions/exceptions.hpp" + Window::Window(const std::string &title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags) - : Window(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, winFlags, drvIndex, renFlags) + : Window(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, winFlags, drvIndex, renFlags) { } Window::Window(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags) { - if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO) { - throw std::runtime_error(std::string("video wasn't inited. Error: ") + SDL_GetError()); - } + if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO) { + throw exceptions::SdlWasNotInit(std::string("video wasn't inited. Error: ") + SDL_GetError()); + } + + if ((winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { + _bFullScreenDesktop = true; + } + else { + _bFullScreenDesktop = false; + } - if ((winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { - _bFullScreenDesktop = true; - } - else { - _bFullScreenDesktop = false; - } + _pWindow = SDL_CreateWindow(title.c_str(), x, y, width, height, winFlags); - _pWindow = SDL_CreateWindow(title.c_str(), x, y, width, height, winFlags); + if (!_pWindow) { + throw exceptions::WindowError("Cannot create Window: " + std::string(SDL_GetError())); + } - if (!_pWindow) { - std::string str = SDL_GetError(); - throw std::runtime_error("Cannot create Window: " + str); - } + _pRenderer = SDL_CreateRenderer(_pWindow, drvIndex, renFlags); - _pRenderer = SDL_CreateRenderer(_pWindow, drvIndex, renFlags); + if (!_pRenderer) { + throw exceptions::RendererError("Cannot create Renderer: " + std::string(SDL_GetError())); + } - if (!_pRenderer) { - std::string str = SDL_GetError(); - throw std::runtime_error("Cannot create Renderer: " + str); - } + _windowId = SDL_GetWindowID(getWindow()); - _windowId = SDL_GetWindowID(getWindow()); + setRendererDrawColor(0, 0, 0, 255); + renderClear(); + renderPresent(); +} - setRendererDrawColor(0, 0, 0, 255); - renderClear(); - renderPresent(); +SDL_Window* Window::getWindow() const noexcept +{ + return _pWindow; } -SDL_Window* Window::getWindow() const +SDL_Renderer* Window::getRenderer() const noexcept { - return _pWindow; + return _pRenderer; } - SDL_Renderer* Window::getRenderer() const { - return _pRenderer; +void Window::setRendererDrawColor(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a) const noexcept +{ + SDL_SetRenderDrawColor(_pRenderer, r, g, b, a); } -void Window::setRendererDrawColor(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a) const +void Window::renderDrawPoints(const SDL_Color& color, const SDL_Point points[], int count) const noexcept { - SDL_SetRenderDrawColor(_pRenderer, r, g, b, a); + SDL_SetRenderDrawColor(getRenderer(), color.r, color.g, color.b, color.a); + SDL_RenderDrawPoints(getRenderer(), points, count); } -void Window::renderClear() const +void Window::renderClear() const noexcept { - SDL_RenderClear(_pRenderer); + SDL_RenderClear(_pRenderer); } -void Window::renderPresent() const +void Window::renderPresent() const noexcept { - SDL_RenderPresent(_pRenderer); + SDL_RenderPresent(_pRenderer); } -void Window::toggleFullscreenDesktop() +void Window::toggleFullscreenDesktop() noexcept { - _bFullScreenDesktop = !_bFullScreenDesktop; - SDL_SetWindowFullscreen(getWindow(), _bFullScreenDesktop ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); + _bFullScreenDesktop = !_bFullScreenDesktop; + SDL_SetWindowFullscreen(getWindow(), _bFullScreenDesktop ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); } -uint32_t Window::getWindowId() const +uint32_t Window::getWindowId() const noexcept { - return _windowId; + return _windowId; } bool Window::handleEvent(SDL_Event& event) { - if (event.window.windowID != getWindowId() || handler == nullptr) { - return false; - } + if (event.window.windowID != getWindowId() || handler == nullptr) { + return false; + } + - - return std::invoke(handler, event, this); + return std::invoke(handler, event, this); } Window::~Window() { - if (_pRenderer != nullptr) { - SDL_DestroyRenderer(_pRenderer); - } + if (_pRenderer != nullptr) { + SDL_DestroyRenderer(_pRenderer); + } - if (_pWindow != nullptr) { - SDL_DestroyWindow(_pWindow); - } + if (_pWindow != nullptr) { + SDL_DestroyWindow(_pWindow); + } } diff --git a/sdl2-vga-terminal/src/Window.hpp b/sdl2-vga-terminal/src/Window.hpp index e4899a4e..ffd12f8b 100644 --- a/sdl2-vga-terminal/src/Window.hpp +++ b/sdl2-vga-terminal/src/Window.hpp @@ -5,34 +5,36 @@ #include #include -class Window +class Window { public: - Window() = delete; - Window(const Window&) = delete; - Window(const Window&&) = delete; - Window& operator=(const Window&) = delete; - Window& operator=(const Window&&) = delete; - Window(const std::string &title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); - Window(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); - SDL_Window* getWindow() const; - SDL_Renderer* getRenderer() const; + Window() = delete; + Window(const Window&) = delete; + Window(const Window&&) = delete; + Window& operator=(const Window&) = delete; + Window& operator=(const Window&&) = delete; + Window(const std::string &title, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); + Window(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags); + SDL_Window* getWindow() const noexcept; + SDL_Renderer* getRenderer() const noexcept; - void setRendererDrawColor(const uint8_t r,const uint8_t g, const uint8_t b, const uint8_t a) const; - void renderClear() const; - void renderPresent() const; - void toggleFullscreenDesktop(); + void setRendererDrawColor(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a) const noexcept; + void renderDrawPoints(const SDL_Color& color, const SDL_Point points[], int count) const noexcept; - uint32_t getWindowId() const; - - typedef std::function handler_t; - handler_t handler = nullptr; - bool handleEvent(SDL_Event& event); + void renderClear() const noexcept; + void renderPresent() const noexcept; + void toggleFullscreenDesktop() noexcept; - virtual ~Window(); + uint32_t getWindowId() const noexcept; + + typedef std::function handler_t; + handler_t handler = nullptr; + bool handleEvent(SDL_Event& event); + + virtual ~Window(); private: - SDL_Window* _pWindow = nullptr; - SDL_Renderer* _pRenderer = nullptr; - uint32_t _windowId; - bool _bFullScreenDesktop = false; + SDL_Window* _pWindow = nullptr; + SDL_Renderer* _pRenderer = nullptr; + uint32_t _windowId; + bool _bFullScreenDesktop = false; }; diff --git a/sdl2-vga-terminal/src/exceptions/exceptions.hpp b/sdl2-vga-terminal/src/exceptions/exceptions.hpp new file mode 100644 index 00000000..b2876464 --- /dev/null +++ b/sdl2-vga-terminal/src/exceptions/exceptions.hpp @@ -0,0 +1,32 @@ +#pragma once + + +#include +#include + +namespace exceptions +{ + class LogicalRenderError : public std::runtime_error + { + public: + explicit LogicalRenderError(const std::string& message) : runtime_error(message) {} + }; + + class SdlWasNotInit : public std::runtime_error + { + public: + explicit SdlWasNotInit(const std::string& message) : runtime_error(message) {} + }; + + class WindowError : public std::runtime_error + { + public: + explicit WindowError(const std::string& message) : runtime_error(message) {} + }; + + class RendererError : public std::runtime_error + { + public: + explicit RendererError(const std::string& message) : runtime_error(message) {} + }; +} // namespace exceptions diff --git a/sdl2-vga-terminal/src/tui/utils.cpp b/sdl2-vga-terminal/src/tui/utils.cpp new file mode 100644 index 00000000..84e2273e --- /dev/null +++ b/sdl2-vga-terminal/src/tui/utils.cpp @@ -0,0 +1,48 @@ +#include "utils.hpp" +#include + +namespace tui +{ +std::pair align3Strings(const std::string& left, const std::string& middle, const std::string& right, const uint8_t width) +{ + constexpr uint8_t markers = 2; + constexpr uint8_t minWidth = 3 + markers; + const uint8_t ls = static_cast(left.size()); + const uint8_t ms = static_cast(middle.size()); + const uint8_t rs = static_cast(right.size()); + const uint8_t stringsSize = ls + ms + rs; + + if (ls == 0 || ms == 0 || rs == 0) { + throw std::invalid_argument("no strings can be empty"); + } + + if (width < minWidth) { + throw std::invalid_argument("width has to be at least " + std::to_string(minWidth)); + } + + if (stringsSize > width - markers) { + // TODO balancing string adding "..." to their max size. ? + throw std::invalid_argument("string truncation not yet implemented"); + } + + const uint8_t wss = width - stringsSize; + const uint8_t s3 = static_cast(wss / 3); + const uint8_t s3r = ((width - stringsSize) % 3) != 0; + + const uint8_t lpad = s3; + const uint8_t mpad = s3 + s3r; + + const uint8_t first = lpad + ls; + const uint8_t second = first + ms + mpad; + + return std::make_pair(first, second); +} + +std::string alignString(const std::string& str, const uint8_t pad, const uint8_t fill) noexcept +{ + uint8_t p2 = pad / 2; + uint8_t pr = pad % 2; + + return std::string(p2, fill) + str + std::string(static_cast(p2 + pr), fill); +} +} // namespace tui diff --git a/sdl2-vga-terminal/src/tui/utils.hpp b/sdl2-vga-terminal/src/tui/utils.hpp new file mode 100644 index 00000000..aad89234 --- /dev/null +++ b/sdl2-vga-terminal/src/tui/utils.hpp @@ -0,0 +1,13 @@ +#pragma once +#include +#include + +namespace tui +{ + /** + * @width is the size of the line. + * @return the position where it start and end the middle string + */ + std::pair align3Strings(const std::string& left, const std::string& middle, const std::string& right, const uint8_t width); + std::string alignString(const std::string& str, const uint8_t pad, const uint8_t fill) noexcept; +} // namespace tui diff --git a/sdl2-vga-terminal/src/vga-terminal.cpp b/sdl2-vga-terminal/src/vga-terminal.cpp index 2db6cc83..ba115499 100644 --- a/sdl2-vga-terminal/src/vga-terminal.cpp +++ b/sdl2-vga-terminal/src/vga-terminal.cpp @@ -4,34 +4,34 @@ const char* VGA_TERMINAL_version() { - return VGA_TERMINAL_VERSION; + return VGA_TERMINAL_VERSION; } VGA_Terminal* VGA_TERMINAL_init() { - VgaTerminal* _term = new VgaTerminal("test", 0, -1, 0); - return reinterpret_cast(_term); + VgaTerminal* _term = new VgaTerminal("test", 0, -1, 0); + return reinterpret_cast(_term); } void VGA_TERMINAL_destroy(VGA_Terminal* term) { - if (nullptr == term) { - return; - } + if (nullptr == term) { + return; + } - const VgaTerminal* _term = reinterpret_cast(term); - delete _term; + const VgaTerminal* _term = reinterpret_cast(term); + delete _term; } void VGA_TERMINAL_writeXY(VGA_Terminal* term, const uint8_t x, const uint8_t y, const char* str, const uint8_t col, const uint8_t bgCol) { - VgaTerminal* _term = reinterpret_cast(term); + VgaTerminal* _term = reinterpret_cast(term); - _term->writeXY(x, y, str, col, bgCol); + _term->writeXY(x, y, str, col, bgCol); } void VGA_TERMINAL_render(VGA_Terminal* term) { - VgaTerminal* _term = reinterpret_cast(term); - _term->render(false); + VgaTerminal* _term = reinterpret_cast(term); + _term->render(false); } diff --git a/sdl2-vga-terminal/src/vgafonts.h b/sdl2-vga-terminal/src/vgafonts.h index 488c9391..a4672590 100644 --- a/sdl2-vga-terminal/src/vgafonts.h +++ b/sdl2-vga-terminal/src/vgafonts.h @@ -21,9 +21,9 @@ constexpr auto VGA_FONT_SIZE_16 = 16; */ static uint8_t vgafont_cursors16[VGA_FONT_CURSORS * VGA_FONT_SIZE_16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, }; @@ -35,780 +35,780 @@ static uint8_t vgafont_cursors16[VGA_FONT_CURSORS * VGA_FONT_SIZE_16] = static uint8_t vgafont8[VGA_FONT_CHARS * VGA_FONT_SIZE_8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, - 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, - 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, - 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, - 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, - 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, - 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, - 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, - 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, - 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, - 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, - 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, - 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, - 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, - 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, - 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, - 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, - 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, - 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, - 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, - 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, - 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, - 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, - 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, - 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, - 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, - 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, - 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, - 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, - 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, - 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, - 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, - 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, - 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, - 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, - 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, - 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, - 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, - 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, - 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, - 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, - 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, - 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, - 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, - 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, - 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, - 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, - 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, - 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, - 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, - 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, - 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, - 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, - 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, - 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, - 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, - 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, - 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, - 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, - 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, - 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, - 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, - 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, - 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, - 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, - 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, - 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, - 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, - 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, - 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, - 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, - 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, - 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, - 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, - 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, - 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, - 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, - 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, - 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, - 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, - 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, - 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, - 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, - 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, - 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, - 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, - 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, - 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, - 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, - 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, - 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, - 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, - 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, - 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, - 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, + 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, + 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, + 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, + 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, + 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, + 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, + 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, + 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, + 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, + 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, + 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, + 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, + 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, + 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, + 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, + 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, + 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, + 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, + 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, + 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, + 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, + 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, + 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, + 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, + 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, + 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, + 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, + 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, + 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, + 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t vgafont14[VGA_FONT_CHARS * VGA_FONT_SIZE_14] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, - 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, - 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t vgafont16[VGA_FONT_CHARS * VGA_FONT_SIZE_16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/sdl2-vga-terminal/src/vgapalette.h b/sdl2-vga-terminal/src/vgapalette.h index 4407e0fc..47837edb 100644 --- a/sdl2-vga-terminal/src/vgapalette.h +++ b/sdl2-vga-terminal/src/vgapalette.h @@ -18,63 +18,63 @@ constexpr auto PALETTE_CHANNELS = 3; static uint8_t palette1[PALETTE_1_COLORS * PALETTE_CHANNELS] = { - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f }; static uint8_t palette2[PALETTE_2_COLORS * PALETTE_CHANNELS] = { - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, - 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, - 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, - 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, - 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, - 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, - 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, + 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, + 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, + 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, + 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, + 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f }; static uint8_t palette3[PALETTE_3_COLORS * PALETTE_CHANNELS] = { - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, - 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, - 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, - 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, - 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, - 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, - 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, + 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, + 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, + 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, + 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, + 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, - 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, - 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, - 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, - 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, - 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, - 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, - 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, - 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, + 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, + 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, + 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, + 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, + 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, + 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, + 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, + 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, - 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, - 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, - 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, - 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, - 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, - 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, - 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, - 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, + 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, + 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, + 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, + 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, + 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, + 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, + 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, + 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, - 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, - 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, - 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, - 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, - 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, - 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, - 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, - 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 + 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, + 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, + 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, + 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, + 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, + 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, + 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 }; diff --git a/sdl2-vga-terminal/test/CMakeLists.txt b/sdl2-vga-terminal/test/CMakeLists.txt index df6a9c17..e3444e69 100644 --- a/sdl2-vga-terminal/test/CMakeLists.txt +++ b/sdl2-vga-terminal/test/CMakeLists.txt @@ -1,55 +1,113 @@ -cmake_minimum_required (VERSION 3.16) - - -find_package(GTest 1.10 CONFIG REQUIRED) - -if (TEST_DUMP_SNAPSHOT) - set (BUILD_SNAPSHOT bool ON) # ON by dependent option configuration anyway, but not hurting - add_compile_definitions(TEST_DUMP_SNAPSHOT) -else() - ### VgaTerminal tests ### - add_executable(runUnitTests "tests.cpp") - add_test(UnitTestsInMain runUnitTests) - target_link_libraries(runUnitTests PRIVATE ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock) - add_custom_command(TARGET runUnitTests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - - - ### Shared Lib tests ### - if (BUILD_SHARED_LIBS) - add_executable(runSOTest "so-test.cpp") - add_test(SOTest runSOTest) - target_link_libraries(runSOTest PRIVATE ${LIB_SDL2main} vga-terminal GTest::gtest) - add_custom_command(TARGET runSOTest POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - endif() -endif() - -### Snapshot tests #### -if (BUILD_SNAPSHOT) - find_package(SDL2-image CONFIG REQUIRED) - - add_executable(runSnapshotTests "snapshotTest.cpp") - target_link_libraries(runSnapshotTests PRIVATE ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock SDL2::SDL2_image) - add_test(SnapshotTestsInMain runSnapshotTests) - add_custom_command(TARGET runSnapshotTests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/snapshot $/snapshot - ) -endif() - -### Valgrind tests ### -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_executable(runHelgrindTests "valgrind/helgrind.cpp") - target_link_libraries(runHelgrindTests PRIVATE ${LIB_SDL2main} vga-terminal-static) - add_executable(runMultiThreadFuzzTests "valgrind/multithreading.cpp") - target_link_libraries(runMultiThreadFuzzTests PRIVATE ${LIB_SDL2main} vga-terminal-static) -endif() +cmake_minimum_required (VERSION 3.16) + +find_package(GTest 1.10 CONFIG REQUIRED) + +macro(macro_test) # ${ARGN} link libraries + + set(prefix TEST) + set(flags SNAPSHOT DEFAULT SHARELIB) + set(singleValues EXE FILE) + set(multiValues LINKS) + + include(CMakeParseArguments) + cmake_parse_arguments(${prefix} "${flags}" "${singleValues}" "${multiValues}" ${ARGN}) + #message("${EXE} - ${FILE} - ${LINKS}") + #message("EXE: ${TEST_EXE}") + #message("FILE: ${TEST_FILE}") + #message("IS DEFAULT: ${TEST_DEFAULT}") + #message("IS SNAPSHOT: ${TEST_SNAPSHOT}") + #message("NEED SHARELIB: ${TEST_SHARELIB}") + #message("LINKS: ${TEST_LINKS}") + add_executable (${TEST_EXE} ${TEST_FILE}) + target_link_libraries(${TEST_EXE} PRIVATE ${TEST_LINKS}) + add_custom_command(TARGET ${TEST_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + + if(${TEST_SNAPSHOT}) + add_custom_command( + TARGET ${TEST_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/snapshot $/snapshot + ) + endif() + + if(${TEST_SHARELIB}) + add_custom_command( + TARGET ${TEST_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + endif() + + include(GoogleTest) + gtest_discover_tests(${TEST_EXE}) +endmacro() + +if (TEST_DUMP_SNAPSHOT) + set (BUILD_SNAPSHOT bool ON) # ON by dependent option configuration anyway, but not hurting + add_compile_definitions(TEST_DUMP_SNAPSHOT) +else() + ### Window tests ### + macro_test( + DEFAULT + EXE runWindowTests + FILE "WindowTest.cpp" + LINKS ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock + ) + + ### VgaTerminal tests ### + macro_test( + DEFAULT + EXE runVgaTerminalTests + FILE "VgaTerminalTest.cpp" + LINKS ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock + ) + + ### tui::utils Tests ### + macro_test( + DEFAULT + EXE runUtilsTests + FILE "tui/utilsTest.cpp" + LINKS ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock + ) + + ### Shared Lib tests ### + if (BUILD_SHARED_LIBS) + macro_test( + SHARELIB + EXE runSOTest + FILE "so-test.cpp" + LINKS ${LIB_SDL2main} vga-terminal GTest::gtest + ) + endif() +endif() + +### Snapshot tests #### +if (BUILD_SNAPSHOT) + find_package(SDL2-image CONFIG REQUIRED) + + ### VgaTerminal Snapshot Tests ### + macro_test( + SNAPSHOT + EXE runVgaTerminalSnapshotTests + FILE "VgaTerminalSnapshotTest.cpp" + LINKS ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock SDL2::SDL2_image + ) + + ### TuiTerminal Snapshot Tests ### + macro_test( + SNAPSHOT + EXE runTuiTerminalSnapshotTests + FILE "TuiTerminalSnapshotTest.cpp" + LINKS ${LIB_SDL2main} vga-terminal-static GTest::gtest GTest::gmock SDL2::SDL2_image + ) +endif() + +### Valgrind tests ### +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + add_executable(runHelgrindTests "valgrind/helgrind.cpp") + target_link_libraries(runHelgrindTests PRIVATE ${LIB_SDL2main} vga-terminal-static) + add_executable(runMultiThreadFuzzTests "valgrind/multithreading.cpp") + target_link_libraries(runMultiThreadFuzzTests PRIVATE ${LIB_SDL2main} vga-terminal-static) +endif() diff --git a/sdl2-vga-terminal/test/Environment.hpp b/sdl2-vga-terminal/test/Environment.hpp index d519e60b..9f229981 100644 --- a/sdl2-vga-terminal/test/Environment.hpp +++ b/sdl2-vga-terminal/test/Environment.hpp @@ -1,30 +1,35 @@ #pragma once -class Environment : public ::testing::Environment { +#include +#include +#include + +class Environment : public ::testing::Environment +{ public: - ~Environment() override {} + ~Environment() override {} - static void setUp() - { - ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS)); - SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); - SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); - } + static void setUp() + { + ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS)); + SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); + } - static void tearDown() - { - SDL_Quit(); - } + static void tearDown() + { + SDL_Quit(); + } - // Override this to define how to set up the environment. - void SetUp() override - { - Environment::setUp(); - } + // Override this to define how to set up the environment. + void SetUp() override + { + Environment::setUp(); + } - // Override this to define how to tear down the environment. - void TearDown() override - { - Environment::tearDown(); - } + // Override this to define how to tear down the environment. + void TearDown() override + { + Environment::tearDown(); + } }; diff --git a/sdl2-vga-terminal/test/Snapshot.hpp b/sdl2-vga-terminal/test/Snapshot.hpp new file mode 100644 index 00000000..e2564f58 --- /dev/null +++ b/sdl2-vga-terminal/test/Snapshot.hpp @@ -0,0 +1,117 @@ +#pragma once + + +#include "Environment.hpp" +#include +#include +#include +#include +#include +#include +#include + + +class SnapshotEnvironment : public Environment +{ + // Override this to define how to set up the environment. + void SetUp() override + { + Environment::setUp(); + ASSERT_NE(0, IMG_Init(IMG_INIT_PNG)); + } + + // Override this to define how to tear down the environment. + void TearDown() override + { + IMG_Quit(); + Environment::tearDown(); + } +}; + +std::string generateSnapshotFilename() +{ + std::string snapshotFilename = ::testing::UnitTest::GetInstance()->current_test_info()->test_case_name(); + snapshotFilename += '.'; + snapshotFilename += ::testing::UnitTest::GetInstance()->current_test_info()->name(); + snapshotFilename += ".png"; + std::replace(snapshotFilename.begin(), snapshotFilename.end(), '/', '-'); + + return snapshotFilename; +} + +SDL_Surface* getScreenshot(SDL_Window* window, SDL_Renderer* renderer) +{ + int w = 0; + int h = 0; + constexpr uint32_t format = SDL_PIXELFORMAT_ABGR8888; + constexpr int depth = 32; + + SDL_GetWindowSize(window, &w, &h); + SDL_Surface* snapshot = SDL_CreateRGBSurfaceWithFormat(0, w, h, depth, format); + + if (SDL_RenderReadPixels(renderer, nullptr, format, snapshot->pixels, snapshot->pitch) != 0) { + GTEST_LOG_(ERROR) << "Unable to take screenshoot:" << SDL_GetError(); + } + + return snapshot; +} + +void snapShotTest(SDL_Window* window, SDL_Renderer* renderer, const std::string& snapshotFilename) +{ + SDL_Surface* snapshot = getScreenshot(window, renderer); + +#ifdef TEST_DUMP_SNAPSHOT + GTEST_LOG_(INFO) << "Dumping snapshot: " << snapshotFilename; + IMG_SavePNG(snapshot, ("snapshot/" + snapshotFilename).c_str()); +#else + SDL_Surface* image = IMG_Load(("snapshot/" + snapshotFilename).c_str()); + ASSERT_FALSE(NULL == image); + ASSERT_FALSE(NULL == image->format); + // SDL_PIXELFORMAT_BGRA32 on CI macos software rendering... cannot investigate further so comment out the check. + EXPECT_EQ(image->format->format, snapshot->format->format); + EXPECT_EQ(image->format->BytesPerPixel, snapshot->format->BytesPerPixel); + EXPECT_EQ(image->pitch, snapshot->pitch); + EXPECT_EQ(image->w, snapshot->w); + EXPECT_EQ(image->h, snapshot->h); + + if (SDL_LockSurface(image) != 0) { + GTEST_LOG_(ERROR) << "unable to access image" << SDL_GetError(); + } + + if (SDL_LockSurface(snapshot) != 0) { + GTEST_LOG_(ERROR) << "unable to access snapshot" << SDL_GetError(); + } + + int size = image->pitch * image->h; + EXPECT_EQ(0, std::memcmp(image->pixels, snapshot->pixels, size)); + if (::testing::Test::HasFailure()) { + // Dump wrong result for inspection. + GTEST_LOG_(ERROR) << "An Error has occorred. Dumping screenshot..."; + IMG_SavePNG(snapshot, ("snapshot/error_" + snapshotFilename).c_str()); + } + + SDL_UnlockSurface(image); + SDL_UnlockSurface(snapshot); + SDL_FreeSurface(image); + + +#endif + SDL_FreeSurface(snapshot); +} + +int snapshotMain(int argc, char** argv) +{ +#ifdef TEST_DUMP_SNAPSHOT + std::cout + << "******************************************************************************************************" << std::endl + << "*** WARNING !!! : DUMPING SCREENSHOT, IF IT IS NOT INTENDED REMOVE THE DEFINE 'TEST_DUMP_SNAPSHOT' ***" << std::endl + << "*** AND RECOMPILE AGAIN. ***" << std::endl + << "*** WARNING !!! : THE FILE ARE AVAILABLE IN THE SUB-DIRECTORY 'snapshot' AND WILL BE REUSED FOR ***" << std::endl + << "*** VERIFYING WHEN NOT DUMPING ***" << std::endl + << "******************************************************************************************************" + << std::endl; +#endif + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/sdl2-vga-terminal/test/TuiTerminalSnapshotTest.cpp b/sdl2-vga-terminal/test/TuiTerminalSnapshotTest.cpp new file mode 100644 index 00000000..b6cbccdb --- /dev/null +++ b/sdl2-vga-terminal/test/TuiTerminalSnapshotTest.cpp @@ -0,0 +1,26 @@ +#include "Snapshot.hpp" +#include + + +TEST(TuiTerminal, Snapshot) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + std::string snapshotFilename = generateSnapshotFilename(); + TuiTerminal tui = TuiTerminal(title, "TUI " + title); + + tui.draw(); + tui.drawSingleBorderDialog({ 0, 0, 22, 5 }, TuiTerminal::defaultCol, TuiTerminal::defaultBgCol, "TUI Dialog", "TUI Dialog Body"); + tui.drawSingleBorderDialog({ 5, 1, 12, 3 }, 14, 1, "TUI On Top", "Shadowing"); + tui.drawDialog({ 20, 5, 20, 10 }, 15, 1, "Header", "Body"); + tui.progressBar(false, true, 22, 10, 15, 50, 100); + tui.progressBar(true, false, 22, 12, 15, 50, 100); + tui.render(true); + + snapShotTest(tui.getWindow(), tui.getRenderer(), snapshotFilename); +} + + +int main(int argc, char** argv) +{ + return snapshotMain(argc, argv); +} diff --git a/sdl2-vga-terminal/test/VgaTerminalSnapshotTest.cpp b/sdl2-vga-terminal/test/VgaTerminalSnapshotTest.cpp new file mode 100644 index 00000000..877c6e54 --- /dev/null +++ b/sdl2-vga-terminal/test/VgaTerminalSnapshotTest.cpp @@ -0,0 +1,65 @@ +#include "Environment.hpp" +#include "Snapshot.hpp" +#include +#include +#include +#include +#include +#include + + +void vgaTerminalSnapShotTest(VgaTerminal& term, const std::string& snapshotFilename) +{ + // TODO this line smells + // BODY a common beaviour of a renderer interface has to be considered now + term.render(true); + + snapShotTest(term.getWindow(), term.getRenderer(), snapshotFilename); +} + +TEST(VgaTerminal, Snapshot) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, 0, -1, 0); + term.showCursor = false; + std::string snapshotFilename = generateSnapshotFilename(); + + for (int i = 0; i < 256; i++) { + term.write(static_cast(i), i, 255 - i); + } + + term.writeXY(32, 11, "ͻ", 14, 1); + term.writeXY(32, 12, " Hello World!! ", 14, 1); + term.writeXY(32, 13, "ͼ", 14, 1); + + vgaTerminalSnapShotTest(term, snapshotFilename); +} + +class CursorShapeTests: public ::testing::TestWithParam {}; +TEST_P(CursorShapeTests, CursorShapeSnapshot) +{ + VgaTerminal::CURSOR_MODE cursorMode = GetParam(); + std::string snapshotFilename = generateSnapshotFilename(); + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, 0, -1, 0); + term.cursor_mode = cursorMode; + term.blinkCursor = false; + term.write(title, 7, 0); + + vgaTerminalSnapShotTest(term, snapshotFilename); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + CursorShapeTests, + ::testing::Values( + VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL, + VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT, + VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK, + VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL + ) +); + +int main(int argc, char** argv) +{ + return snapshotMain(argc, argv); +} diff --git a/sdl2-vga-terminal/test/VgaTerminalTest.cpp b/sdl2-vga-terminal/test/VgaTerminalTest.cpp new file mode 100644 index 00000000..d80bf267 --- /dev/null +++ b/sdl2-vga-terminal/test/VgaTerminalTest.cpp @@ -0,0 +1,617 @@ +#include +#include +#include +#include +#include +#include "Environment.hpp" +#include +#include + + +void cmpViewportCheck(const SDL_Rect& vp, const SDL_Rect& exp) +{ + EXPECT_EQ(vp.x, exp.x); + EXPECT_EQ(vp.y, exp.y); + EXPECT_EQ(vp.w, exp.w); + EXPECT_EQ(vp.h, exp.h); +} + +void cmpTerminalChar(const VgaTerminal::terminalChar_t& tc1, const VgaTerminal::terminalChar_t& tc2) +{ + EXPECT_EQ(tc1.bgCol, tc2.bgCol); + EXPECT_EQ(tc1.c, tc2.c); + EXPECT_EQ(tc1.col, tc2.col); +} + +// expect around ~10% tolerance on the given value to be matched +void cmpTicks(const uint64_t start, const uint64_t end, const uint16_t value) +{ + double te = ceil(static_cast(value) * 0.10); + double diff = static_cast(end - start)/ (SDL_GetPerformanceFrequency()/1000.0); + double dt = abs(diff - static_cast(value)); + GTEST_LOG_(INFO) << "value=" << value << " --- diff=" << diff << " --- te=" << te << " --- dt=" << dt; + EXPECT_LE(dt, te); +} + +TEST(VgaTerminal, checkVersion) +{ + VgaTerminal t("", 0, -1, 0); + ASSERT_STRCASEEQ("0.3.0", t.getVersion().c_str()); +} + +TEST(VgaTerminal, CannotInit) +{ + // NOTE: using the env ptr, generate a segFault at the end of the test.. weird. + // so created 2 static wrapper. + Environment::tearDown(); + ASSERT_THROW(VgaTerminal term = VgaTerminal("", 0, -1, 0), std::runtime_error); + ASSERT_THROW(VgaTerminal term = VgaTerminal("", 0, -1, 0), exceptions::SdlWasNotInit); + Environment::setUp(); +} + +TEST(VgaTerminal, TimerNotInitedWarning) +{ + Environment::tearDown(); + ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO)); + SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); + { + testing::internal::CaptureStderr(); + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + std::string output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output, testing::EndsWith("TIMER or EVENTS not inited.\n")); + EXPECT_THAT(output, testing::HasSubstr("WARN:")); + } + Environment::tearDown(); + Environment::setUp(); +} + +TEST(VgaTerminal, HelloWorldWindowMinimal) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title); + ASSERT_EQ(SDL_GetWindowTitle(term.getWindow()), title); +} + +TEST(VgaTerminal, HelloWorldWindow) { + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + ASSERT_EQ(SDL_GetWindowTitle(term.getWindow()), title); +} + +TEST(VgaTerminal, HelloWorldText) { + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.write(title, 7, 0); + uint8_t termTitleLength = static_cast(title.size()); + EXPECT_EQ(VgaTerminal::position_t(termTitleLength, 0), term.getXY()); + EXPECT_EQ(VgaTerminal::position_t(termTitleLength, 0), VgaTerminal::position_t(term.getX(), term.getY())); + EXPECT_EQ(title[6], term.at(6, 0).c); +} + +TEST(VgaTerminal, ScrollDown) { + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.writeXY(term.getMode().tw - 1, term.getMode().th - 1, title, 7, 1); + uint8_t titleLength = static_cast(title.size()); + + EXPECT_EQ(VgaTerminal::position_t(titleLength - 1, term.getMode().th - 1), term.getXY()); + EXPECT_EQ(title[0], term.at(term.getMode().tw - 1, term.getMode().th - 2).c); + EXPECT_EQ(title[6], term.at(5, term.getMode().th - 1).c); +} + +TEST(VgaTerminal, scrollDownReusingSameGridChar) +{ + // TODO how to verify? + // BODY mocks and call some private method once? + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.writeXY(0, 24, "a", 7, 1); + term.writeXY(0, 23, "a", 7, 1); + VgaTerminal::terminalChar_t tc = term.at(0, 23); + term.newLine(); + cmpTerminalChar(tc, term.at(0, 23)); + cmpTerminalChar(VgaTerminal::terminalChar_t{ 0, 0, 0 }, term.at(0, 25)); +} + +TEST(VgaTerminal, clearLine) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.write(title, 7, 1); + cmpTerminalChar(term.at(0, 0), VgaTerminal::terminalChar_t({ 'c', 7, 1 })); + term.clearLine(0); + cmpTerminalChar(term.at(0, 0), VgaTerminal::terminalChar_t({ 0, 0, 0 })); +} + +TEST(VgaTerminal, clearLineViewport) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.writeXY(9, 2, "X", 7, 1); + term.writeXY(21, 2, "X", 7, 1); + EXPECT_TRUE(term.setViewPort(10, 2, 10, 2)); + term.write(title, 7, 1); + term.clearLine(0); + cmpTerminalChar(term.at(0, 0), VgaTerminal::terminalChar_t({ 0, 0, 0 })); + term.resetViewport(); + cmpTerminalChar(term.at(9, 2), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); + cmpTerminalChar(term.at(21, 2), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); +} + +TEST(VgaTerminal, clearLineOutsideViewport) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + testing::internal::CaptureStderr(); + term.clearLine(100); + std::string output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output, testing::HasSubstr("WARN: [")); + EXPECT_THAT(output, testing::EndsWith("VgaTerminal] clearLine: y outside viewport\n")); +} + +TEST(VgaTerminal, fill) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + EXPECT_TRUE(term.setViewPort(1, 1, 5, 2)); + term.fill('X', 7, 1); + term.resetViewport(); + cmpTerminalChar(term.at(1, 1), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); + cmpTerminalChar(term.at(0, 1), VgaTerminal::terminalChar_t({ 0, 0, 0 })); +} + +TEST(VgaTerminal, fillRestoreAndNoAutoScroll) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.autoScroll = false; + term.fill('X', 7, 1); + cmpTerminalChar(term.at(79, 24), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); + EXPECT_FALSE(term.autoScroll); +} + +TEST(VgaTerminal, doNotRenderTwiceIfAlreadyRendered) +{ + // TODO: how to verify without mocking? + // BODY only with mocking at the moment i have a solution but require some restructure... + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.write("Hello", 7, 1); + term.render(); + // here the expect internal method should not be used... + term.render(); +} + +TEST(VgaTerminal, notRenderingWhenWindowHidden) +{ + // This test makes the reported code coverage not correct + // or is related to some other code, but not for this test suite, + // because render is never call. + // TODO: how to verify without mocking? + // BODY only with mocking at the moment i have a solution but require some restructure... + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.write("Hello", 7, 1); + term.render(); + // expect term.renderPresent() to be called once +} + +TEST(VgaTerminal, forceReRendering) +{ + // TODO: how to verify without mocking? + // BODY only with mocking at the moment i have a solution but require some restructure... + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, 0, -1, 0); + term.write("Hello", 7, 1); + term.render(); + term.render(true); +} + +TEST(VgaTerminal, atOutOfViewport) +{ + // TODO _defaultChar_t consideration + // BODY this test might bring the consideration to return/have something different + // rather that {0, 0, 0} when wrong input for .at + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + SDL_Rect vp = term.getViewport(); + for (int i = 1; i < vp.w * vp.h; i++) { + term.write('X', 7, 1); + } + + cmpTerminalChar(term.at(vp.w + 1, 0), VgaTerminal::terminalChar_t({ 0, 0, 0 })); + + cmpTerminalChar(term.at(11, 6), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); + term.setViewPort(VgaTerminal::position_t(0, 0), 10, 5); + cmpTerminalChar(term.at(11, 6), VgaTerminal::terminalChar_t({ 0, 0, 0 })); +} + +TEST(VgaTerminal, moveCursorClockWise) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + + term.gotoXY(VgaTerminal::position_t(10, 10)); + term.moveCursorLeft(); + EXPECT_EQ(9, term.getX()); + EXPECT_EQ(10, term.getY()); + term.moveCursorDown(); + EXPECT_EQ(9, term.getX()); + EXPECT_EQ(11, term.getY()); + term.moveCursorRight(); + EXPECT_EQ(10, term.getX()); + EXPECT_EQ(11, term.getY()); + term.moveCursorUp(); + EXPECT_EQ(10, term.getX()); + EXPECT_EQ(10, term.getY()); +} + +TEST(VgaTerminal, NoAutoScroll) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.autoScroll = false; + term.writeXY(79, 24, "0", 7, 0); + EXPECT_EQ(79, term.getX()); + EXPECT_EQ(24, term.getY()); + + term.writeXY(79, 20, "0", 7, 0); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(21, term.getY()); +} + +TEST(VgaTerminal, clear) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + const char c = 'X'; + const uint8_t col = 7; + const uint8_t bgCol = 1; + + term.write(c, col, bgCol); + auto tc = term.at(0, 0); + EXPECT_EQ(c, tc.c); + EXPECT_EQ(col, tc.col); + EXPECT_EQ(bgCol, tc.bgCol); + + term.clear(); + tc = term.at(0, 0); + EXPECT_EQ(0, tc.c); + EXPECT_EQ(0, tc.col); + EXPECT_EQ(0, tc.bgCol); +} + +TEST(VgaTerminal, clearViewport) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + const char c = 'X'; + const char c2 = 'Y'; + const uint8_t col = 7; + const uint8_t bgCol = 1; + + term.gotoXY(9, 10); + term.write(c2, col, bgCol); + + ASSERT_TRUE(term.setViewPort(10, 10, 10, 10)); + + term.write(c, col, bgCol); + auto tc = term.at(0, 0); + EXPECT_EQ(c, tc.c); + EXPECT_EQ(col, tc.col); + EXPECT_EQ(bgCol, tc.bgCol); + + term.clear(); + tc = term.at(0, 0); + EXPECT_EQ(0, tc.c); + EXPECT_EQ(0, tc.col); + EXPECT_EQ(0, tc.bgCol); + + term.resetViewport(); + tc = term.at(9, 10); + EXPECT_EQ(c2, tc.c); + EXPECT_EQ(col, tc.col); + EXPECT_EQ(bgCol, tc.bgCol); +} + +TEST(VgaTerminal, resetViewport) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + auto vp = term.getViewport(); + SDL_Rect vp2 = { 10, 10, 10, 10 }; + ASSERT_TRUE(term.setViewPort(vp2)); + cmpViewportCheck(vp2, term.getViewport()); + term.resetViewport(); + cmpViewportCheck(vp, term.getViewport()); +} + +TEST(VgaTerminal, setViewportLargerThanTerminalMode) +{ + using ::testing::HasSubstr; + using ::testing::EndsWith; + + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + SDL_Rect vp = { 0, 0, term.getMode().tw + 1, term.getMode().th }; + + testing::internal::CaptureStderr(); + EXPECT_FALSE(term.setViewPort(vp)); + std::string output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output, HasSubstr("WARN: [")); + EXPECT_THAT(output, EndsWith("VgaTerminal] setViewPort: viewport larger than terminal.\n")); +} + +TEST(VgaTerminal, Idle) +{ + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.cursor_time = 1000; + EXPECT_TRUE(term.isIdle()); + term.write("X", 7, 1); + EXPECT_FALSE(term.isIdle()); +} + +TEST(VgaTerminal, cursorNoBlinking) +{ + SDL_Event e; + std::memset(&e, 0, sizeof(SDL_Event)); + SDL_EventState(SDL_WINDOWEVENT, SDL_DISABLE); + + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + term.blinkCursor = false; + term.setCursorSpeed(VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_FAST); + uint16_t cursorWaitTime = static_cast(term.getCursorSpeed()) * 2; + + // flush the SDL_event queue too... + SDL_FlushEvents(0, 0xFFFFFFFF); + EXPECT_EQ(0, SDL_WaitEventTimeout(&e, cursorWaitTime)); + EXPECT_EQ(e.type, 0); +} + +class CursorBlinkingTests: public ::testing::TestWithParam {}; +TEST_P(CursorBlinkingTests, cursorBlinking) +{ + uint16_t cursorTime = GetParam(); + uint16_t cursorWaitTime = cursorTime * 4; + SDL_Event e; + std::memset(&e, 0, sizeof(SDL_Event)); + SDL_EventState(SDL_WINDOWEVENT, SDL_DISABLE); + + std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); + uint16_t old_time = term.cursor_time; + term.cursor_time = cursorTime; + EXPECT_EQ(old_time, static_cast(VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_NORMAL)); + SDL_FlushEvents(0, 0xFFFFFFFF); + // Discard first "blink" as it could be the default one + EXPECT_EQ(1, SDL_WaitEventTimeout(&e, cursorWaitTime)); + uint64_t start = SDL_GetPerformanceCounter(); + ASSERT_EQ(1, SDL_WaitEventTimeout(&e, cursorWaitTime)); + uint64_t end = SDL_GetPerformanceCounter(); + + EXPECT_EQ(e.type, SDL_USEREVENT); + EXPECT_EQ(e.window.windowID, term.getWindowId()); + EXPECT_EQ(e.user.code, 0); + EXPECT_TRUE(NULL == e.user.data1); + EXPECT_TRUE(NULL == e.user.data2); + EXPECT_EQ(e.user.type, SDL_USEREVENT); // ??? + EXPECT_EQ(e.user.windowID, term.getWindowId()); + // give some tollerance (~2%) +#ifndef NO_PRECISE_TIMER + cmpTicks(start, end, cursorTime); +#endif +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + CursorBlinkingTests, + ::testing::Values( + 500, + VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_NORMAL, + VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_SLOW, + VgaTerminal::CURSOR_SPEED::CURSOR_SPEED_FAST + ) +); + +class SetViewportParameterTests: public ::testing::TestWithParam> {}; +TEST_P(SetViewportParameterTests, SetVieport) +{ + int vx = std::get<0>(GetParam()); + int vy = std::get<1>(GetParam()); + int vw = std::get<2>(GetParam()); + int vh = std::get<3>(GetParam()); + bool autoScroll = std::get<4>(GetParam()); + int x = std::get<5>(GetParam()); + int y = std::get<6>(GetParam()); + + VgaTerminal term = VgaTerminal("SetViewport Test", SDL_WINDOW_HIDDEN, -1, 0); + term.autoScroll = autoScroll; + + EXPECT_TRUE(term.setViewPort(vx, vy, vw, vh)); + auto e = term.getViewport(); + EXPECT_EQ(vx, e.x); + EXPECT_EQ(vy, e.y); + EXPECT_EQ(vw, e.w); + EXPECT_EQ(vh, e.h); + term.writeXY(x, y, "X", 15, 1); + auto tc = term.at(x, y); + EXPECT_EQ('X', tc.c); + EXPECT_EQ(15, tc.col); + EXPECT_EQ(1, tc.bgCol); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + SetViewportParameterTests, + ::testing::Values( + std::make_tuple(0, 0, 1, 1, false, 0, 0), // SetViewport1 + std::make_tuple(10, 10, 10, 10, true, 0, 0), // SetViewport2 + std::make_tuple(5, 4, 20, 20, true, 5, 5) // atViewport + ) +); + +class SetViewportNullErrTests: public ::testing::TestWithParam> {}; +TEST_P(SetViewportNullErrTests, setViewportNullError) +{ + using ::testing::HasSubstr; + using ::testing::EndsWith; + + SDL_Rect vp; + vp.x = std::get<0>(GetParam()); + vp.y = std::get<1>(GetParam()); + vp.w = std::get<2>(GetParam()); + vp.h = std::get<3>(GetParam()); + + VgaTerminal term = VgaTerminal("setViewportNullErr", SDL_WINDOW_HIDDEN, -1, 0); + + testing::internal::CaptureStderr(); + EXPECT_FALSE(term.setViewPort(vp)); + std::string output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output, HasSubstr("WARN: [")); + EXPECT_THAT(output, EndsWith("VgaTerminal] setViewPort: viewport too small.\n")); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + SetViewportNullErrTests, + ::testing::Values( + std::make_tuple(0, 0, 0, 0), + std::make_tuple(0, 0, 1, 0), + std::make_tuple(0, 0, 1, 0) + ) +); + +class MoveCursorBorderCW: public ::testing::TestWithParam> {}; +TEST_P(MoveCursorBorderCW, moveCursorBoderCW) +{ + SDL_Rect vp; + vp.x = std::get<0>(GetParam()); + vp.y = std::get<1>(GetParam()); + vp.w = std::get<2>(GetParam()); + vp.h = std::get<3>(GetParam()); + ASSERT_GT(vp.h, 3); + ASSERT_GT(vp.w, 2); + + VgaTerminal term = VgaTerminal("SetViewport Test", SDL_WINDOW_HIDDEN, -1, 0); + ASSERT_TRUE(term.setViewPort(vp)); + + + term.gotoXY(vp.w - 1, vp.h - 2); + term.moveCursorRight(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(vp.h - 1, term.getY()); + term.moveCursorDown(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(vp.h - 1, term.getY()); + term.moveCursorLeft(); + EXPECT_EQ(vp.w - 1, term.getX()); + EXPECT_EQ(vp.h - 2, term.getY()); + term.moveCursorUp(); + EXPECT_EQ(vp.w - 1, term.getX()); + EXPECT_EQ(vp.h - 3, term.getY()); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + MoveCursorBorderCW, + ::testing::Values( + std::make_tuple(0, 0, 80, 25), + std::make_tuple(10, 10, 10, 10) + ) +); + +class NewLineParameterTests: public ::testing::TestWithParam> {}; +TEST_P(NewLineParameterTests, newLine) +{ + int x = std::get<0>(GetParam()); + int y = std::get<1>(GetParam()); + bool autoScroll = std::get<2>(GetParam()); + + VgaTerminal term = VgaTerminal("newLine", SDL_WINDOW_HIDDEN, -1, 0); + term.autoScroll = autoScroll; + auto vp = term.getViewport(); + char c = 'X'; + uint8_t col = 7; + uint8_t bgCol = 1; + + ASSERT_GE(vp.h, 2); + + term.gotoXY(x, y); + term.newLine(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(x+1, term.getY()); + + term.writeXY(x, vp.h - 1, std::string(1, c), 7, 1); + term.newLine(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(vp.h - 1, term.getY()); + + // check if it is really move on a new line, scrolling the terminal + auto tc = term.at(x, vp.h - 1 - static_cast(autoScroll)); + EXPECT_EQ(c, tc.c); + EXPECT_EQ(col, tc.col); + EXPECT_EQ(bgCol, tc.bgCol); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + NewLineParameterTests, + ::testing::Values( + std::make_tuple(10, 10, true), // NewLine + std::make_tuple(10, 10, false) // no autoscroll + ) +); + +class NewLineViewPortTests: public ::testing::TestWithParam {}; +TEST_P(NewLineViewPortTests, newLineViewport) +{ + bool autoScroll = GetParam(); + VgaTerminal term = VgaTerminal("newLine", SDL_WINDOW_HIDDEN, -1, 0); + term.autoScroll = autoScroll; + std::string str = "X"; + uint8_t col = 7; + uint8_t bgCol = 1; + + //viewport + term.setViewPort(5, 4, 20, 20); + term.writeXY(5, 18, str, col, bgCol); + term.newLine(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(19, term.getY()); + + auto tc = term.at(5, 18); + EXPECT_EQ(str[0], tc.c); + EXPECT_EQ(7, tc.col); + EXPECT_EQ(1, tc.bgCol); + + term.clear(); + term.writeXY(5, 19, str, col, bgCol); + term.newLine(); + EXPECT_EQ(0, term.getX()); + EXPECT_EQ(19, term.getY()); + + tc = term.at(5, 19 - static_cast(autoScroll)); + EXPECT_EQ(str[0], tc.c); + EXPECT_EQ(col, tc.col); + EXPECT_EQ(bgCol, tc.bgCol); +} +INSTANTIATE_TEST_SUITE_P( + VgaTerminal, + NewLineViewPortTests, + ::testing::Values( + true, + false + ) +); + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/sdl2-vga-terminal/test/WindowTest.cpp b/sdl2-vga-terminal/test/WindowTest.cpp new file mode 100644 index 00000000..24960af1 --- /dev/null +++ b/sdl2-vga-terminal/test/WindowTest.cpp @@ -0,0 +1,19 @@ +#include +#include +#include +#include "Environment.hpp" +#include + +TEST(Window, cannotInit) +{ + Environment::tearDown(); + ASSERT_THROW(Window term = Window("", 320, 200, 0, -1, 0), exceptions::SdlWasNotInit); + ASSERT_THROW(Window term = Window("", 0, 0, 320, 200, 0, -1, 0), exceptions::SdlWasNotInit); + Environment::setUp(); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/sdl2-vga-terminal/test/snapshot/TuiTerminal.Snapshot.png b/sdl2-vga-terminal/test/snapshot/TuiTerminal.Snapshot.png new file mode 100644 index 0000000000000000000000000000000000000000..c91d6c675d988a2a335d49d51fb0eef693ad9e20 GIT binary patch literal 6544 zcmeHMc~n#9wof93(iZR)+iFG78lhYftplix7OjLq6s?F+!c{QHC?Hb;36?6YR?vWe zAi=7Dh!7d0Kn7YZLzJitAq)Y95G25Xgd}9XCj=DN>wWjFckg;{t+(z!EWWe$+57kX z_HXZRpD#b}-?!J`qc1;#Kp+MP*WKO_2rL-_fnNDg7kuIc1&z3Wi?jfwuS zsNU^W$p?ah564RAR-1c%uiwToOEdq(<>xy=zpkVw-1A0X5kLAWEn*o(go zaU;Ob2f)4t4UT{Yc-o}%jLwvwn`Iyo$j1FbfFm}Xt$&ga0lhcrZo)1WIu;evFu@w%mA$AkC;`qN{025RE3e@L!8jZLloeppc9q^>2l> zN5kpCHQQ?J>h-Io*zfyPe3lFSg)zPMi>3*iYY9~K^c1rywVmkDHxt~TYU8p{sMz6G z6fTQ}+VV$4sSmAKlq>6)uygE)-rLpGDUyzreB=|MZV$|p@mh5rNV7gxu<`dz)zH43 z%l#beYvZI_j4C#$*Cx&g_-g(yv$Xv+`9m(0*np%4+3cvyUf^VfCF4bw%aKi_@>3dC za&C$6!{v?$)zb-T?t{?&y(O_}Mxwr}+hpS<%lER1F;8_KlyZ`AkFT{fmg-;1v}{Vn zgzh-ki!4PR9P$>ByxJ$cmT3|;Wt+*pN!iKCcDy>|vVmN4%5mD>iyz(L0g3rlg!d0o zxWgIvjzWrwSzS-pkCUAvz*E5KL=y4MQ{C=5eDOmit1NS~SNk%I#iWE*@JVma^|M%X zRyUpmTV94?b1uIi0TtUk_c^0Fk^ zI`Z3YJdG61)?*S^y?H8$9Ogxf#YjM^8tGA;&Yg@vsaU#GN*{vCkjD9#G+{7UEEL|& zD2UFJQn<~)uAWJeYDB5bkifD)omw-Y9hYi}*fnp~H>KW*z0`|OSVh+roVhq-uUT(_ zX2KC)-hZgf<}EIa|D;Yd6zi+EC!ikz@Mf>3eNI-(YM{RmAu8o&L%*I~1h}ZbQ`s&D zbO=$fQMKthgtz)SB+J`F2}itiec}np|G)}CSmxcQV))X*B3Sceg608Phah~rc`m+{ zu`^g-jqfeKOoVOsJb1lG-m6lr0pF=TF+LSWEILgrdgSYF8Exr=Aiz_nTU8~Q-rk|F z%ae?!X*vXWORk>@@j66fU!?E<0}6&91bBKvj1`}PJt8C+mNS^`Oo00yG^Xol&2u5< zv+J(F5nUZRn;JKsgCi=7%#-zT`fvnc+cv1jl>2G~;eN?~%atG7Nr`l`EL2z(DuTL5 zh>>(sfgXY|yp&4A%Zf9jq;4Pvb{fqldB@}@AbKZ~KInYdKUV|Su;^d3;J8@|S$f`i zp6!P=n|Odcye8@2?1 z2{J9^XL!ru@nG1)zGalET^NY~nQd2R>5$<$P!%=j@PzG3dfBrB9T(nonoq^n_ckYC zwcaZ(r6!}o?uL`)dy680nXxr}ab`GNtW*?pKSJK>@&uUDPV+n(b}2z^p)1eH7}2`&`v zE*D?8UpOEVGtHYCcM}5EV?I2xDs#yHD@5gIVGyVNcxDB|PrDBVzijX*r=ekIhPe6C zHoWZo&2$b8Z4rD-s%mRE5;IbZvu;1Tam5@t6{Q9@(>et}Ja)+_B^g1mznz+_7ep*J zXU;gxyQ_wp+~l&KZ17SOv$gT+<1Lm>uvix&j%x!}Lk|i2frFOZ!_?13njXHw@H zZ`Sz7?AKb{-wd_Kz<%puWSJz4MiJ8;8WQT2RI_w#I%v^mZO2sOG5FW9JriS%{xDa9 z3FDqIoqKB1n2A7!|Hxr4qhO`nQ-W!&NBXuo3x|uT(4Y}MV=lD0XVACxOFX&v5{J! zXFqj4pS7~W%YJu*Wa&(CgcH?7&lo`{>+WOF69oa64uq)Dxmp(TdLfR%At{78ip=pzp=fWxm5Hlkq#fs!eRMRvNA(vznYXKaIS@KX4wTVT-tGV7BilUQI zPQ!`L-(zxA*Lsz8eFe0FV|k6GdMRK@MOiuM?Js7CzDzFMZMIv}7I+ZD=k-QmYUFX2C8cPJC6%;tG^DRV(hBo z{A9z;6N#_;UAusR(zVAOmU}=Dgp=$iI%gi8#wdL8s`|=r7)P|cj-P^cyW8XdXBX)B zVkMnx_gAZdRYShWjK(V9R^)I9Hlta@D{yFNP++lmv{Ld%_x=%WGObNv)?B7%2j{y9 z_Jt7st068oi!2-uA(an}N~Xqz>2fMnC7MXDk*;4STMgF4w)z~1KAfCs>_*jN~ucr&SzqF>0doPS&atuFbJGN12G7djhBvmjARK~Af{%9z`j zvXAD2W|=-xR8_^L|$==qfbu zx42yM3OQeZVUW&UK1RC6&V=D37{i+jg3E>6ODQ+~#5@_);a2D&J#8iIF?No54$4#K z3VcVFdGgpz?GA%rcMa<>n{vQL+*HXn80-cTe|4Hi|11pBgljw*wjka@9_V?#5k?z3 zzXAS7QC{loUyzXAb%^RG>JnMd!Y(w>wEzjKQ<{JO0abq|^dkIo zLs5->v(m9}_EdMJw+CwDAybM9QCUtig;6nq12MJ9BUxC^)M0j)(q{waN?>JtREg zK8Xj}eD0{@S$PnD%}^PMQkS-tMN8a{d766Vw#J;Lb4B0eHrRILRjNcw)XMUv0xnNN zt)-@w^(Muv!kS4?Gct=7SuW^?#!qOU4!$KBk495#Z7b{qRStH(p%fBeJBKy@gQswn zua}XNX}`0BoJb4V95;flQ`A!w)wz2j^*FWvsyAb@ZBRIyXrAmb*j+XdJJE`yvS%m< z=QgnO;~f3WuP*t4ULaSnK2!0!(Z?V;QSC+v(DIyQgSfX z-d-`bp)YilV>!p7gWeVWj@xm>B|*Ztnz=nMg0IQeynmE2NZ(?Z%D$Sij2&)Lf(yNo^wqx{?K^4_>bY{mX(_RDWar@>1H24PUGnR7=XnXt~S1# zyCWq2_}hFJ9Vi%YzT}$T-zf@#xmG%8pjEGs2H0S+T5VM&zn{%{IE#|}kFhT@7VQK% z9UvX#m9-usY16%Lwa3l4d(U}TmD6WFEK(e74Vy?@(yX&s-QEFj8C`g+zuNfgJ)die ziVEiG<}%;6d-}KW{}memtuS-SuJJ{F>$MSS57()GB32C)@DkjV(>b6Bg-;k@zXR1k zS7AfF&GO1Z&C<0})F`tX?`wl$I#OTSdwHoFWY~m@ni|v8zyoz<=#1kIXhZ)bUYStc zKmqy^ab9l~Ax33g=2(~~W5dF1vdQYuuZ~2dEME|YzdDdTS|c!_*R?mkEj9T@#&wdyntF-9>^=LW6R_FwM|dFA`lNZrdvW|8M?_`YaTaT-8Esa0_HEl~3Q>OEewl}>t_YTvfaIihYc zVQue>wm{)6j$6TlrN$@g zat=6Di+=?ZdzVrf`WPH@D~&W8o46LZ_7ph5B?W=aUK8OPa3ULb(KK#sAp0lqlRUso zbFTiAp(5sP{+7jEIEkUDiGmKL5$(I+N3|+H^ddnlRK2E{{{OW`d4%OU#lACVfxv!y zFMQHIna5mV%0rgq47Hs(q~?tGhvOqYDrBCGQMP@t5u83W()5IU_O2Fawpergy@C0o zPIK@t943oSxqm{?ulBVcDte=;MJZPgY;B5kCTtV!TRl!k66CuG0V^>UO9>5k=8iY> zrwMaeo>Rog za75H5Pw-<7uGjwW#h-GZsYxR5EAR&I8<~a75TvjqTx}|Km-J4Mn4YC2ufm1^D~n55 z6uz@7kla&8@sYf;3s>6}7c+VjB$xYvDW`|8 z(j@!RF9()7*&+y;#aFV=y-6^h{kh9{CrHWq@7WOX&PQX@Sn!fhDe2OkiWCE~8pz(i z$VWB?w^QQkeQ4GQLV4V1+2AeIhcb4|4T{Q(vUH|u3l5d(gH#3*|)p= ITmK*a2Jsi#E&u=k literal 0 HcmV?d00001 diff --git a/sdl2-vga-terminal/test/snapshotTest.cpp b/sdl2-vga-terminal/test/snapshotTest.cpp deleted file mode 100644 index 77283d27..00000000 --- a/sdl2-vga-terminal/test/snapshotTest.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -std::string generateSnapshotFilename() -{ - std::string snapshotFilename = ::testing::UnitTest::GetInstance()->current_test_info()->test_case_name(); - snapshotFilename += '.'; - snapshotFilename += ::testing::UnitTest::GetInstance()->current_test_info()->name(); - snapshotFilename += ".png"; - std::replace(snapshotFilename.begin(), snapshotFilename.end(), '/', '-'); - return snapshotFilename; -} - -SDL_Surface* getScreenshot(const VgaTerminal& term) -{ - int w = 0, h = 0; - const uint32_t format = SDL_PIXELFORMAT_ABGR8888; - - SDL_GetWindowSize(term.getWindow(), &w, &h); - SDL_Surface* snapshot = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, format); - - if (SDL_RenderReadPixels(term.getRenderer(), NULL, format, snapshot->pixels, snapshot->pitch) != 0) { - GTEST_LOG_(ERROR) << "Unable to take screenshoot:" << SDL_GetError(); - } - - return snapshot; -} - -void snapShotTest(VgaTerminal& term, const std::string& snapshotFilename) -{ - term.render(); - - SDL_Surface* snapshot = getScreenshot(term); - -#ifdef TEST_DUMP_SNAPSHOT - GTEST_LOG_(INFO) << "Dumping snapshot: " << snapshotFilename; - IMG_SavePNG(snapshot, ("snapshot/" + snapshotFilename).c_str()); -#else - SDL_Surface* image = IMG_Load(("snapshot/" + snapshotFilename).c_str()); - ASSERT_FALSE(NULL == image); - ASSERT_FALSE(NULL == image->format); - EXPECT_EQ(image->format->format, snapshot->format->format); - EXPECT_EQ(image->format->BytesPerPixel, snapshot->format->BytesPerPixel); - EXPECT_EQ(image->pitch, snapshot->pitch); - EXPECT_EQ(image->w, snapshot->w); - EXPECT_EQ(image->h, snapshot->h); - - if (SDL_LockSurface(image) != 0) { - GTEST_LOG_(ERROR) << "unable to access image" << SDL_GetError(); - } - - if (SDL_LockSurface(snapshot) != 0) { - GTEST_LOG_(ERROR) << "unable to access snapshot" << SDL_GetError(); - } - - int size = image->pitch * image->h; - EXPECT_EQ(0, std::memcmp(image->pixels, snapshot->pixels, size)); - - SDL_UnlockSurface(image); - SDL_UnlockSurface(snapshot); - SDL_FreeSurface(image); -#endif - SDL_FreeSurface(snapshot); -} - -TEST(VgaTerminal, Snapshot) -{ - ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO)); - ASSERT_NE(0, IMG_Init(IMG_INIT_PNG)); - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, 0, -1, 0); - term.showCursor = false; - std::string snapshotFilename = generateSnapshotFilename(); - - for (int i = 0; i < 256; i++) { - term.write(static_cast(i), i, 255 - i); - } - - term.writeXY(32, 11, "ͻ", 14, 1); - term.writeXY(32, 12, " Hello World!! ", 14, 1); - term.writeXY(32, 13, "ͼ", 14, 1); - - snapShotTest(term, snapshotFilename); - - IMG_Quit(); - SDL_Quit(); -} - -class CursorShapeTests: public ::testing::TestWithParam {}; -TEST_P(CursorShapeTests, CursorShapeSnapshot) -{ - VgaTerminal::CURSOR_MODE cursorMode = GetParam(); - ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS)); - ASSERT_NE(0, IMG_Init(IMG_INIT_PNG)); - std::string snapshotFilename = generateSnapshotFilename(); - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, 0, -1, 0); - term.cursor_mode = cursorMode; - term.write(title, 7, 0); - - snapShotTest(term, snapshotFilename); - - IMG_Quit(); - SDL_Quit(); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - CursorShapeTests, - ::testing::Values( - VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL, - VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT, - VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK, - VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL - ) -); - -int main(int argc, char** argv) { -#ifdef TEST_DUMP_SNAPSHOT - std::cout - << "******************************************************************************************************" << std::endl - << "*** WARNING !!! : DUMPING SCREENSHOT, IF IT IS NOT INTENDED REMOVE THE DEFINE 'TEST_DUMP_SNAPSHOT' ***" << std::endl - << "*** AND RECOMPILE AGAIN. ***" << std::endl - << "*** WARNING !!! : THE FILE ARE AVAILABLE IN THE SUB-DIRECTORY 'snapshot' AND WILL BE REUSED FOR ***" << std::endl - << "*** VERIFYING WHEN NOT DUMPING ***" << std::endl - << "******************************************************************************************************" - << std::endl; -#endif - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdl2-vga-terminal/test/so-test.cpp b/sdl2-vga-terminal/test/so-test.cpp index 36c19d6d..b3280441 100644 --- a/sdl2-vga-terminal/test/so-test.cpp +++ b/sdl2-vga-terminal/test/so-test.cpp @@ -4,20 +4,20 @@ TEST(VgaTerminalSO, simpleRunningTest) { - ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)); - - VGA_Terminal* term = VGA_TERMINAL_init(); - VGA_TERMINAL_writeXY(term, 0, 0, "test", 10, 0); - VGA_TERMINAL_render(term); - ASSERT_STRCASEEQ("0.2.2", VGA_TERMINAL_version()); - VGA_TERMINAL_destroy(term); + ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)); - SDL_Quit(); + VGA_Terminal* term = VGA_TERMINAL_init(); + VGA_TERMINAL_writeXY(term, 0, 0, "test", 10, 0); + VGA_TERMINAL_render(term); + ASSERT_STRCASEEQ("0.3.0", VGA_TERMINAL_version()); + VGA_TERMINAL_destroy(term); + + SDL_Quit(); } int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); + ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + return RUN_ALL_TESTS(); } diff --git a/sdl2-vga-terminal/test/tests.cpp b/sdl2-vga-terminal/test/tests.cpp deleted file mode 100644 index df711570..00000000 --- a/sdl2-vga-terminal/test/tests.cpp +++ /dev/null @@ -1,514 +0,0 @@ -#include -#include -#include -#include -#include -#include "Environment.hpp" -#include - - -void cmpViewportCheck(const SDL_Rect& vp, const SDL_Rect& exp) -{ - EXPECT_EQ(vp.x, exp.x); - EXPECT_EQ(vp.y, exp.y); - EXPECT_EQ(vp.w, exp.w); - EXPECT_EQ(vp.h, exp.h); -} - -void cmpTerminalChar(const VgaTerminal::terminalChar_t& tc1, const VgaTerminal::terminalChar_t& tc2) -{ - EXPECT_EQ(tc1.bgCol, tc2.bgCol); - EXPECT_EQ(tc1.c, tc2.c); - EXPECT_EQ(tc1.col, tc2.col); -} - -// expect around ~1% tolerance on the given value to be matched -void cmpTicks(const uint32_t start, const uint32_t end, const uint16_t value) -{ - double te = static_cast(value) * 0.01; - double t = abs(static_cast(end - start) - value) - te; - EXPECT_LE(t, 1); -} - -TEST(VgaTerminal, checkVersion) -{ - VgaTerminal t("", 0, -1, 0); - ASSERT_STRCASEEQ("0.2.2", t.getVersion().c_str()); -} - -TEST(VgaTerminal, CannotInit) -{ - // NOTE: using the env ptr, generate a segFault at the end of the test.. weird. - // so created 2 static wrapper. - Environment::tearDown(); - ASSERT_THROW(VgaTerminal term = VgaTerminal("", 0, -1, 0), std::runtime_error); - Environment::setUp(); -} - -TEST(VgaTerminal, TimerNotInitedWarning) -{ - Environment::tearDown(); - ASSERT_EQ(0, SDL_Init(SDL_INIT_VIDEO)); - SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); - { - testing::internal::CaptureStderr(); - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - std::string output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output, testing::EndsWith("TIMER or EVENTS not inited.\n")); - EXPECT_THAT(output, testing::HasSubstr("WARN:")); - } - Environment::tearDown(); - Environment::setUp(); -} - -TEST(VgaTerminal, HelloWorldWindow) { - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - - ASSERT_EQ(SDL_GetWindowTitle(term.getWindow()), title); -} - -TEST(VgaTerminal, HelloWorldText) { - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - - term.write(title, 7, 0); - uint8_t termTitleLength = static_cast(title.size()); - EXPECT_EQ(VgaTerminal::position_t(termTitleLength, 0), term.getXY()); - EXPECT_EQ(VgaTerminal::position_t(termTitleLength, 0), VgaTerminal::position_t(term.getX(), term.getY())); - EXPECT_EQ(title[6], term.at(6, 0).c); -} - -TEST(VgaTerminal, ScrollDown) { - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - - term.writeXY(term.getMode().tw - 1, term.getMode().th - 1, title, 7, 1); - uint8_t titleLength = static_cast(title.size()); - - EXPECT_EQ(VgaTerminal::position_t(titleLength - 1, term.getMode().th - 1), term.getXY()); - EXPECT_EQ(title[0], term.at(term.getMode().tw - 1, term.getMode().th - 2).c); - EXPECT_EQ(title[6], term.at(5, term.getMode().th - 1).c); -} - -TEST(VgaTerminal, scrollDownReusingSameGridChar) -{ - // TODO how to verify? - // BODY mocks and call some private method once? - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - term.writeXY(0, 24, "a", 7, 1); - term.writeXY(0, 23, "a", 7, 1); - VgaTerminal::terminalChar_t tc = term.at(0, 23); - term.newLine(); - cmpTerminalChar(tc, term.at(0, 23)); - cmpTerminalChar(VgaTerminal::terminalChar_t{ 0, 0, 0 }, term.at(0, 25)); -} - -TEST(VgaTerminal, doNotRenderTwiceIfAlreadyRendered) -{ - // TODO: how to verify without mocking? - // BODY only with mocking at the moment i have a solution but require some restructure... - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - term.write("Hello", 7, 1); - term.render(); - // here the expect internal method should not be used... - term.render(); -} - -TEST(VgaTerminal, notRenderingWhenWindowHidden) -{ - // This test makes the reported code coverage not correct - // or is related to some other code, but not for this test suite, - // because render is never call. - // TODO: how to verify without mocking? - // BODY only with mocking at the moment i have a solution but require some restructure... - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - term.write("Hello", 7, 1); - term.render(); - // expect term.renderPresent() to be called once -} - -TEST(VgaTerminal, forceReRendering) -{ - // TODO: how to verify without mocking? - // BODY only with mocking at the moment i have a solution but require some restructure... - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, 0, -1, 0); - term.write("Hello", 7, 1); - term.render(); - term.render(true); -} - -TEST(VgaTerminal, atOutOfViewport) -{ - // TODO _defaultChar_t consideration - // BODY this test might bring the consideration to return/have something different - // rather that {0, 0, 0} when wrong input for .at - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - SDL_Rect vp = term.getViewport(); - for (int i = 1; i < vp.w * vp.h; i++) { - term.write('X', 7, 1); - } - - cmpTerminalChar(term.at(vp.w + 1, 0), VgaTerminal::terminalChar_t({ 0, 0, 0 })); - - cmpTerminalChar(term.at(11, 6), VgaTerminal::terminalChar_t({ 'X', 7, 1 })); - term.setViewPort(VgaTerminal::position_t(0, 0), 10, 5); - cmpTerminalChar(term.at(11, 6), VgaTerminal::terminalChar_t({ 0, 0, 0 })); -} - - -TEST(VgaTerminal, moveCursorClockWise) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - - term.gotoXY(VgaTerminal::position_t(10, 10)); - term.moveCursorLeft(); - EXPECT_EQ(9, term.getX()); - EXPECT_EQ(10, term.getY()); - term.moveCursorDown(); - EXPECT_EQ(9, term.getX()); - EXPECT_EQ(11, term.getY()); - term.moveCursorRight(); - EXPECT_EQ(10, term.getX()); - EXPECT_EQ(11, term.getY()); - term.moveCursorUp(); - EXPECT_EQ(10, term.getX()); - EXPECT_EQ(10, term.getY()); -} - -TEST(VgaTerminal, NoAutoScroll) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - term.autoScroll = false; - term.writeXY(79, 24, "0", 7, 0); - EXPECT_EQ(79, term.getX()); - EXPECT_EQ(24, term.getY()); - - term.writeXY(79, 20, "0", 7, 0); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(21, term.getY()); -} - -TEST(VgaTerminal, clear) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - const char c = 'X'; - const uint8_t col = 7; - const uint8_t bgCol = 1; - - term.write(c, col, bgCol); - auto tc = term.at(0, 0); - EXPECT_EQ(c, tc.c); - EXPECT_EQ(col, tc.col); - EXPECT_EQ(bgCol, tc.bgCol); - - term.clear(); - tc = term.at(0, 0); - EXPECT_EQ(0, tc.c); - EXPECT_EQ(0, tc.col); - EXPECT_EQ(0, tc.bgCol); -} - -TEST(VgaTerminal, clearViewport) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - const char c = 'X'; - const char c2 = 'Y'; - const uint8_t col = 7; - const uint8_t bgCol = 1; - - term.gotoXY(9, 10); - term.write(c2, col, bgCol); - - ASSERT_TRUE(term.setViewPort(10, 10, 10, 10)); - - term.write(c, col, bgCol); - auto tc = term.at(0, 0); - EXPECT_EQ(c, tc.c); - EXPECT_EQ(col, tc.col); - EXPECT_EQ(bgCol, tc.bgCol); - - term.clear(); - tc = term.at(0, 0); - EXPECT_EQ(0, tc.c); - EXPECT_EQ(0, tc.col); - EXPECT_EQ(0, tc.bgCol); - - term.resetViewport(); - tc = term.at(9, 10); - EXPECT_EQ(c2, tc.c); - EXPECT_EQ(col, tc.col); - EXPECT_EQ(bgCol, tc.bgCol); -} - -TEST(VgaTerminal, resetViewport) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - auto vp = term.getViewport(); - SDL_Rect vp2 = { 10, 10 ,10, 10 }; - ASSERT_TRUE(term.setViewPort(vp2)); - cmpViewportCheck(vp2, term.getViewport()); - term.resetViewport(); - cmpViewportCheck(vp, term.getViewport()); -} - -TEST(VgaTerminal, setViewportLargerThanTerminalMode) -{ - using ::testing::HasSubstr; - using ::testing::EndsWith; - - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - SDL_Rect vp = { 0, 0, term.getMode().tw + 1, term.getMode().th }; - - testing::internal::CaptureStderr(); - EXPECT_FALSE(term.setViewPort(vp)); - std::string output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output, HasSubstr("WARN: [")); - EXPECT_THAT(output, EndsWith("VgaTerminal] setViewPort: viewport larger than terminal.\n")); -} - -TEST(VgaTerminal, Idle) -{ - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - term.cursor_time = 1000; - EXPECT_TRUE(term.isIdle()); - term.write("X", 7, 1); - EXPECT_FALSE(term.isIdle()); -} - -class CursorBlinkingTests: public ::testing::TestWithParam {}; -TEST_P(CursorBlinkingTests, cursorBlinking) -{ - uint16_t cursorTime = GetParam(); - SDL_Event e; - std::memset(&e, 0, sizeof(SDL_Event)); - - std::string title = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - VgaTerminal term = VgaTerminal(title, SDL_WINDOW_HIDDEN, -1, 0); - - uint32_t init = SDL_GetTicks(); - uint16_t old_time = term.cursor_time; - term.cursor_time = cursorTime; - ASSERT_EQ(1, SDL_WaitEventTimeout(&e, 1000)); - uint32_t start = SDL_GetTicks(); - ASSERT_EQ(1, SDL_WaitEventTimeout(&e, cursorTime * 2)); - uint32_t end = SDL_GetTicks(); - - EXPECT_EQ(e.type, SDL_USEREVENT); - EXPECT_EQ(e.window.windowID, term.getWindowId()); - EXPECT_EQ(e.user.code, 0); - EXPECT_TRUE(NULL == e.user.data1); - EXPECT_TRUE(NULL == e.user.data2); - EXPECT_EQ(e.user.type, SDL_USEREVENT); // ??? - EXPECT_EQ(e.user.windowID, term.getWindowId()); - // give a tollerance of 1% - cmpTicks(start, end, cursorTime); - cmpTicks(init, start, old_time); -} - -class SetViewportParameterTests: public ::testing::TestWithParam> {}; -TEST_P(SetViewportParameterTests, SetVieport) -{ - int vx = std::get<0>(GetParam()); - int vy = std::get<1>(GetParam()); - int vw = std::get<2>(GetParam()); - int vh = std::get<3>(GetParam()); - bool autoScroll = std::get<4>(GetParam()); - int x = std::get<5>(GetParam()); - int y = std::get<6>(GetParam()); - - VgaTerminal term = VgaTerminal("SetViewport Test", SDL_WINDOW_HIDDEN, -1, 0); - term.autoScroll = autoScroll; - - EXPECT_TRUE(term.setViewPort(vx, vy, vw, vh)); - auto e = term.getViewport(); - EXPECT_EQ(vx, e.x); - EXPECT_EQ(vy, e.y); - EXPECT_EQ(vw, e.w); - EXPECT_EQ(vh, e.h); - term.writeXY(x, y, "X", 15, 1); - auto tc = term.at(x, y); - EXPECT_EQ('X', tc.c); - EXPECT_EQ(15, tc.col); - EXPECT_EQ(1, tc.bgCol); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - SetViewportParameterTests, - ::testing::Values( - std::make_tuple(0, 0, 1, 1, false, 0, 0), // SetViewport1 - std::make_tuple(10, 10, 10, 10, true, 0, 0), // SetViewport2 - std::make_tuple(5, 4, 20, 20, true, 5, 5) // atViewport - ) -); - -class SetViewportNullErrTests: public ::testing::TestWithParam> {}; -TEST_P(SetViewportNullErrTests, setViewportNullError) -{ - using ::testing::HasSubstr; - using ::testing::EndsWith; - - SDL_Rect vp; - vp.x = std::get<0>(GetParam()); - vp.y = std::get<1>(GetParam()); - vp.w = std::get<2>(GetParam()); - vp.h = std::get<3>(GetParam()); - - VgaTerminal term = VgaTerminal("setViewportNullErr", SDL_WINDOW_HIDDEN, -1, 0); - - testing::internal::CaptureStderr(); - EXPECT_FALSE(term.setViewPort(vp)); - std::string output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output, HasSubstr("WARN: [")); - EXPECT_THAT(output, EndsWith("VgaTerminal] setViewPort: viewport too small.\n")); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - SetViewportNullErrTests, - ::testing::Values( - std::make_tuple(0, 0, 0, 0), - std::make_tuple(0, 0, 1, 0), - std::make_tuple(0, 0, 1, 0) - ) -); - -class MoveCursorBorderCW: public ::testing::TestWithParam> {}; -TEST_P(MoveCursorBorderCW, moveCursorBoderCW) -{ - SDL_Rect vp; - vp.x = std::get<0>(GetParam()); - vp.y = std::get<1>(GetParam()); - vp.w = std::get<2>(GetParam()); - vp.h = std::get<3>(GetParam()); - ASSERT_GT(vp.h, 3); - ASSERT_GT(vp.w, 2); - - VgaTerminal term = VgaTerminal("SetViewport Test", SDL_WINDOW_HIDDEN, -1, 0); - ASSERT_TRUE(term.setViewPort(vp)); - - - term.gotoXY(vp.w - 1, vp.h - 2); - term.moveCursorRight(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(vp.h - 1, term.getY()); - term.moveCursorDown(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(vp.h - 1, term.getY()); - term.moveCursorLeft(); - EXPECT_EQ(vp.w - 1, term.getX()); - EXPECT_EQ(vp.h - 2, term.getY()); - term.moveCursorUp(); - EXPECT_EQ(vp.w - 1, term.getX()); - EXPECT_EQ(vp.h - 3, term.getY()); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - MoveCursorBorderCW, - ::testing::Values( - std::make_tuple(0, 0, 80, 25), - std::make_tuple(10, 10, 10, 10) - ) -); - -class NewLineParameterTests: public ::testing::TestWithParam> {}; -TEST_P(NewLineParameterTests, newLine) -{ - int x = std::get<0>(GetParam()); - int y = std::get<1>(GetParam()); - bool autoScroll = std::get<2>(GetParam()); - - VgaTerminal term = VgaTerminal("newLine", SDL_WINDOW_HIDDEN, -1, 0); - term.autoScroll = autoScroll; - auto vp = term.getViewport(); - char c = 'X'; - uint8_t col = 7; - uint8_t bgCol = 1; - - ASSERT_GE(vp.h, 2); - - term.gotoXY(x, y); - term.newLine(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(x+1, term.getY()); - - term.writeXY(x, vp.h - 1, std::string(1, c), 7, 1); - term.newLine(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(vp.h - 1, term.getY()); - - // check if it is really move on a new line, scrolling the terminal - auto tc = term.at(x, vp.h - 1 - static_cast(autoScroll)); - EXPECT_EQ(c, tc.c); - EXPECT_EQ(col, tc.col); - EXPECT_EQ(bgCol, tc.bgCol); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - NewLineParameterTests, - ::testing::Values( - std::make_tuple(10, 10, true), // NewLine - std::make_tuple(10, 10, false) // no autoscroll - ) -); - -class NewLineViewPortTests: public ::testing::TestWithParam {}; -TEST_P(NewLineViewPortTests, newLineViewport) -{ - bool autoScroll = GetParam(); - VgaTerminal term = VgaTerminal("newLine", SDL_WINDOW_HIDDEN, -1, 0); - term.autoScroll = autoScroll; - std::string str = "X"; - uint8_t col = 7; - uint8_t bgCol = 1; - - //viewport - term.setViewPort(5, 4, 20, 20); - term.writeXY(5, 18, str, col, bgCol); - term.newLine(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(19, term.getY()); - - auto tc = term.at(5, 18); - EXPECT_EQ(str[0], tc.c); - EXPECT_EQ(7, tc.col); - EXPECT_EQ(1, tc.bgCol); - - term.clear(); - term.writeXY(5, 19, str, col, bgCol); - term.newLine(); - EXPECT_EQ(0, term.getX()); - EXPECT_EQ(19, term.getY()); - - tc = term.at(5, 19 - static_cast(autoScroll)); - EXPECT_EQ(str[0], tc.c); - EXPECT_EQ(col, tc.col); - EXPECT_EQ(bgCol, tc.bgCol); -} -INSTANTIATE_TEST_SUITE_P( - VgaTerminal, - NewLineViewPortTests, - ::testing::Values( - true, - false - ) -); - - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - ::testing::AddGlobalTestEnvironment(new Environment()); - return RUN_ALL_TESTS(); -} diff --git a/sdl2-vga-terminal/test/tui/utilsTest.cpp b/sdl2-vga-terminal/test/tui/utilsTest.cpp new file mode 100644 index 00000000..e8b4ac7b --- /dev/null +++ b/sdl2-vga-terminal/test/tui/utilsTest.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include "../Environment.hpp" + + +class AlignStringTests : public ::testing::TestWithParam> {}; +TEST_P(AlignStringTests, alignString) +{ + std::string str = std::get<0>(GetParam()); + uint8_t pad = std::get<1>(GetParam()); + std::string exp = std::get<2>(GetParam()); + + EXPECT_EQ(tui::alignString(str, pad, ' '), exp); +} +INSTANTIATE_TEST_SUITE_P( + utils, + AlignStringTests, + ::testing::Values( + std::make_tuple("", 0, ""), + std::make_tuple("", 1, " "), + std::make_tuple("", 2, " "), + std::make_tuple("x", 0, "x"), + std::make_tuple("x", 1, "x "), + std::make_tuple("x", 2, " x "), + std::make_tuple("xx", 0, "xx"), + std::make_tuple("xx", 1, "xx "), + std::make_tuple("xx", 2, " xx ") + ) +); + +class Align3StringsTests : public ::testing::TestWithParam> {}; +TEST_P(Align3StringsTests, align3Strings) +{ + std::string left = std::get<0>(GetParam()); + std::string middle = std::get<1>(GetParam()); + std::string right = std::get<2>(GetParam()); + uint8_t expl = std::get<3>(GetParam()); + uint8_t expr = std::get<4>(GetParam()); + std::string exp = std::get<5>(GetParam()); + uint8_t width = exp.size(); + + auto [lmark, rmark] = tui::align3Strings(left, middle, right, width); + uint8_t lpad = lmark - left.size(); + uint8_t mpad = rmark - lmark - middle.size() - 1; + uint8_t rpad = width - rmark - right.size() - 1; + + std::string res = tui::alignString(left, lpad, ' ')+ "|" + + tui::alignString(middle, mpad, ' ') + "|" + + tui::alignString(right, rpad, ' '); + EXPECT_EQ(res.size(), width); + EXPECT_STRCASEEQ(exp.c_str(), res.c_str()); + EXPECT_EQ(lmark, expl); + EXPECT_EQ(rmark, expr); +} +INSTANTIATE_TEST_SUITE_P( + utils, + Align3StringsTests, + ::testing::Values( //012345678901234567890 + std::make_tuple("a", "b", "c", 1, 3, "a|b|c"), // 0 + std::make_tuple("a", "b", "c", 2, 4, "a |b|c"), // 1 + std::make_tuple("a", "b", "c", 2, 5, "a |b |c"), // 2 + std::make_tuple("a", "b", "c", 2, 5, "a |b |c "), // 3 + std::make_tuple("a", "b", "c", 3, 7, " a | b |c "), // 4 + std::make_tuple("a", "b", "c", 3, 6, " a |b |c "), // 5 + std::make_tuple("a", "b", "c", 3, 7, " a | b |c "), // 6 + std::make_tuple("a", "b", "c", 3, 7, " a | b | c "), // 7 + //012345678901234567890123456789012345678901234567890 + std::make_tuple("TITLE", "DESCRIPTION", "VERSION", 07, 21, " TITLE | DESCRIPTION | VERSION "), // 8 + std::make_tuple("TITLE", "DESCRIPTION", "VERSION", 12, 31, " TITLE | DESCRIPTION | VERSION ") // 9 + ) +); + +class Align3StringsInvalidArgumentTests : public ::testing::TestWithParam> {}; +TEST_P(Align3StringsInvalidArgumentTests, align3StringsInvalidArgument) +{ + std::string left = std::get<0>(GetParam()); + std::string middle = std::get<1>(GetParam()); + std::string right = std::get<2>(GetParam()); + uint8_t width = std::get<3>(GetParam()); + + EXPECT_THROW(tui::align3Strings(left, middle, right, width), std::invalid_argument); +} +INSTANTIATE_TEST_SUITE_P( + utils, + Align3StringsInvalidArgumentTests, + ::testing::Values( + std::make_tuple("", "", "", 0), + std::make_tuple("a", "", "", 0), + std::make_tuple("a", "b", "", 0), + std::make_tuple("a", "b", "c", 0), + std::make_tuple("a", "b", "c", 1), + std::make_tuple("a", "b", "c", 3), + std::make_tuple("a", "b", "c", 4), + std::make_tuple("aa", "b", "c", 5) + ) +); + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/sdl2-vga-terminal/test/valgrind/helgrind.cpp b/sdl2-vga-terminal/test/valgrind/helgrind.cpp index 951e34e9..a8899fe1 100644 --- a/sdl2-vga-terminal/test/valgrind/helgrind.cpp +++ b/sdl2-vga-terminal/test/valgrind/helgrind.cpp @@ -1,134 +1,138 @@ #include #include #include +#include -using namespace std; int main(int argc, char* args[]) { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); - return 1; - } - // --- end SDL2 system init and info - - VgaTerminal term1 = VgaTerminal("VgaTerminal1", 0, 0, 640, 400, 0, -1, 0); - VgaTerminal term2 = VgaTerminal("VgaTerminal2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 400, 0, -1, 0); - - - term1.cursor_time = 100; - term2.cursor_time = 100; - - for (int i = 0; i < 256; i++) { - term1.write(static_cast(i), i, 255 - i); - term2.write(static_cast(i), i, 255 - i); - } - - term1.render(); - term1.writeXY(10, 15, "ͻ", 14, 2); - term1.writeXY(10, 16, " ", 14, 2); - term1.writeXY(10, 17, "ͼ", 14, 2); - term1.gotoXY(12, 16); term1.write(3, 4, 15); - term1.gotoXY(14, 16); term1.write(4, 15, 4); - term1.gotoXY(16, 16); term1.write(5, 0, 15); - term1.gotoXY(18, 16); term1.write(6, 15, 0); - term1.render(); - term1.gotoXY(40, 24); - - term2.writeXY(40, 10, "Terminal II", 7, 0); - - - term1.render(); - term2.render(); - - SDL_Event e; - for (int i = 0; i < 10;) { - SDL_WaitEvent(&e); - if (e.window.windowID == term1.getWindowId()) { - term1.render(); - i++; - } - else if (e.window.windowID == term2.getWindowId()) { - term2.render(); - i++; - } - else { - // ignoring - } - } - - srand(time(0)); - VgaTerminal* term; - for (int i = 0; i < 100; i++) { - if (i % 10) { - term = &term1; - } - else { - term = &term2; - } - - term->write(i % 256, 14, 1); - - switch (rand() % 5) { - case 0: - term->moveCursorLeft(); - break; - case 1: - term->moveCursorRight(); - break; - case 2: - term->moveCursorUp(); - break; - case 3: - term->moveCursorDown(); - break; - case 4: - term->newLine(); - break; - } - - if (rand() % 2) { - term->clear(); - } - - if (rand() % 4 == 0) { - term->write(" cursor_mode: ", 8, 7); - switch (rand() % 4) { - case 0: - term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL; - term->write("NORMAL", 15, 10); - break; - case 1: - term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT; - term->write("FAT", 15, 10); - break; - case 2: - term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; - term->write("BLOCK", 15, 10); - break; - case 3: - term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL; - term->write("VERTICAL", 15, 10); - break; - } - } - - if (rand() % 5) { - term->resetViewport(); - term->setViewPort(term->getViewport()); - term->resetViewport(); - } - - if (rand() % 2) { - term->cursor_time = rand() % 1000; - term->write(" cursor time:", 15, 1); - term->write(std::to_string(term->cursor_time).c_str(), 15, 2); - } - - - term->render(); - } - - SDL_Quit(); - return 0; + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + // --- end SDL2 system init and info + + VgaTerminal term1 = VgaTerminal("VgaTerminal1", 0, 0, 640, 400, 0, -1, 0); + VgaTerminal term2 = VgaTerminal("VgaTerminal2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 400, 0, -1, 0); + + + term1.cursor_time = 100; + term2.cursor_time = 100; + + for (int i = 0; i < 256; i++) { + term1.write(static_cast(i), i, 255 - i); + term2.write(static_cast(i), i, 255 - i); + } + + term1.render(); + term1.writeXY(10, 15, "ͻ", 14, 2); + term1.writeXY(10, 16, " ", 14, 2); + term1.writeXY(10, 17, "ͼ", 14, 2); + term1.gotoXY(12, 16); + term1.write(3, 4, 15); + term1.gotoXY(14, 16); + term1.write(4, 15, 4); + term1.gotoXY(16, 16); + term1.write(5, 0, 15); + term1.gotoXY(18, 16); + term1.write(6, 15, 0); + term1.render(); + term1.gotoXY(40, 24); + + term2.writeXY(40, 10, "Terminal II", 7, 0); + + + term1.render(); + term2.render(); + + SDL_Event e; + for (int i = 0; i < 10;) { + SDL_WaitEvent(&e); + if (e.window.windowID == term1.getWindowId()) { + term1.render(); + i++; + } + else if (e.window.windowID == term2.getWindowId()) { + term2.render(); + i++; + } + else { + // ignoring + } + } + + srand(time(0)); + VgaTerminal* term; + for (int i = 0; i < 100; i++) { + if (i % 10) { + term = &term1; + } + else { + term = &term2; + } + + term->write(i % 256, 14, 1); + + switch (rand() % 5) { + case 0: + term->moveCursorLeft(); + break; + case 1: + term->moveCursorRight(); + break; + case 2: + term->moveCursorUp(); + break; + case 3: + term->moveCursorDown(); + break; + case 4: + term->newLine(); + break; + } + + if (rand() % 2) { + term->clear(); + } + + if (rand() % 4 == 0) { + term->write(" cursor_mode: ", 8, 7); + switch (rand() % 4) { + case 0: + term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL; + term->write("NORMAL", 15, 10); + break; + case 1: + term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT; + term->write("FAT", 15, 10); + break; + case 2: + term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; + term->write("BLOCK", 15, 10); + break; + case 3: + term->cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL; + term->write("VERTICAL", 15, 10); + break; + } + } + + if (rand() % 5) { + term->resetViewport(); + term->setViewPort(term->getViewport()); + term->resetViewport(); + } + + if (rand() % 2) { + term->cursor_time = rand() % 1000; + term->write(" cursor time:", 15, 1); + term->write(std::to_string(term->cursor_time).c_str(), 15, 2); + } + + + term->render(); + } + + SDL_Quit(); + return 0; } diff --git a/sdl2-vga-terminal/test/valgrind/multithreading.cpp b/sdl2-vga-terminal/test/valgrind/multithreading.cpp index c397ed95..96b272d6 100644 --- a/sdl2-vga-terminal/test/valgrind/multithreading.cpp +++ b/sdl2-vga-terminal/test/valgrind/multithreading.cpp @@ -7,120 +7,120 @@ using namespace std; void vgaTerminalOps(VgaTerminal& term) { - for (int i = 0; i < 100; i++) { - term.write(i % 256, 14, 1); - - switch (rand() % 5) { - case 0: - term.moveCursorLeft(); - break; - case 1: - term.moveCursorRight(); - break; - case 2: - term.moveCursorUp(); - break; - case 3: - term.moveCursorDown(); - break; - case 4: - term.newLine(); - break; - } - - if (rand() % 2) { - term.clear(); - } - - if (rand() % 4 == 0) { - term.write(" cursor_mode: ", 8, 7); - switch (rand() % 4) { - case 0: - term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL; - term.write("NORMAL", 15, 10); - break; - case 1: - term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT; - term.write("FAT", 15, 10); - break; - case 2: - term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; - term.write("BLOCK", 15, 10); - break; - case 3: - term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL; - term.write("VERTICAL", 15, 10); - break; - } - } - - if (rand() % 5) { - term.resetViewport(); - term.setViewPort(term.getViewport()); - term.resetViewport(); - } - - if (rand() % 2) { - term.cursor_time = rand() % 1000; - term.write(" cursor time:", 15, 1); - term.write(std::to_string(term.cursor_time).c_str(), 15, 2); - } - } - - term.render(); + for (int i = 0; i < 100; i++) { + term.write(i % 256, 14, 1); + + switch (rand() % 5) { + case 0: + term.moveCursorLeft(); + break; + case 1: + term.moveCursorRight(); + break; + case 2: + term.moveCursorUp(); + break; + case 3: + term.moveCursorDown(); + break; + case 4: + term.newLine(); + break; + } + + if (rand() % 2) { + term.clear(); + } + + if (rand() % 4 == 0) { + term.write(" cursor_mode: ", 8, 7); + switch (rand() % 4) { + case 0: + term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_NORMAL; + term.write("NORMAL", 15, 10); + break; + case 1: + term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_FAT; + term.write("FAT", 15, 10); + break; + case 2: + term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_BLOCK; + term.write("BLOCK", 15, 10); + break; + case 3: + term.cursor_mode = VgaTerminal::CURSOR_MODE::CURSOR_MODE_VERTICAL; + term.write("VERTICAL", 15, 10); + break; + } + } + + if (rand() % 5) { + term.resetViewport(); + term.setViewPort(term.getViewport()); + term.resetViewport(); + } + + if (rand() % 2) { + term.cursor_time = rand() % 1000; + term.write(" cursor time:", 15, 1); + term.write(std::to_string(term.cursor_time).c_str(), 15, 2); + } + } + + term.render(); } void concurrencyBeginVgaTerm(VgaTerminal& term1) { - for (int i = 0; i < 256; i++) { - term1.write(static_cast(i), i, 255 - i); - } - - term1.render(); - - SDL_Event e; - for (int i = 0; i < 3;) { - SDL_WaitEvent(&e); - if (e.window.windowID == term1.getWindowId()) { - term1.render(); - i++; - } - else { - // ignoring - } - } + for (int i = 0; i < 256; i++) { + term1.write(static_cast(i), i, 255 - i); + } + + term1.render(); + + SDL_Event e; + for (int i = 0; i < 3;) { + SDL_WaitEvent(&e); + if (e.window.windowID == term1.getWindowId()) { + term1.render(); + i++; + } + else { + // ignoring + } + } } int main(int argc, char* args[]) { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); - return 1; - } - // --- end SDL2 system init and info - - VgaTerminal term1 = VgaTerminal("VgaTerminal1", 0, 0, 640, 400, 0, -1, 0); - term1.cursor_time = 100; - constexpr int num_threads = 10; - std::thread threads[num_threads]; - - for (int i = 0; i < num_threads; i++) { - threads[i] = std::thread(concurrencyBeginVgaTerm, std::ref(term1)); - } - - for (int i = 0; i < num_threads; i++) { - threads[i].join(); - } - - srand(time(0)); - for (int i = 0; i < num_threads; i++) { - threads[i] = std::thread(vgaTerminalOps, std::ref(term1)); - } - - for (int i = 0; i < num_threads; i++) { - threads[i].join(); - } - - - SDL_Quit(); - return 0; + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Unable to initialize SDL: %s", SDL_GetError()); + return 1; + } + // --- end SDL2 system init and info + + VgaTerminal term1 = VgaTerminal("VgaTerminal1", 0, 0, 640, 400, 0, -1, 0); + term1.cursor_time = 100; + constexpr int num_threads = 10; + std::thread threads[num_threads]; + + for (int i = 0; i < num_threads; i++) { + threads[i] = std::thread(concurrencyBeginVgaTerm, std::ref(term1)); + } + + for (int i = 0; i < num_threads; i++) { + threads[i].join(); + } + + srand(time(0)); + for (int i = 0; i < num_threads; i++) { + threads[i] = std::thread(vgaTerminalOps, std::ref(term1)); + } + + for (int i = 0; i < num_threads; i++) { + threads[i].join(); + } + + + SDL_Quit(); + return 0; } diff --git a/sonar-project.properties b/sonar-project.properties index c5cf681a..7d0f5782 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,5 +6,5 @@ sonar.tests=sdl2-vga-terminal/test sonar.cfamily.build-wrapper-output=build/bw-output sonar.cfamily.threads=2 sonar.cfamily.cache.enabled=false -sonar.cfamily.gcov.reportsPath=build -#sonar.cfamily.llvm-cov.reportPath=build +sonar.cfamily.gcov.reportsPath=build/** +#sonar.cfamily.llvm-cov.reportPath=build/**