diff --git a/.travis.yml b/.travis.yml index f5077ff7ec..99473a46ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,33 +4,70 @@ language: cpp env: - PPSSPP_BUILD_TYPE=Linux + CMAKE=TRUE - PPSSPP_BUILD_TYPE=Android + - PPSSPP_BUILD_TYPE=Blackberry + CMAKE=TRUE + - PPSSPP_BUILD_TYPE=Symbian compiler: - - clang - gcc -before_install: - - sudo add-apt-repository -y ppa:ubuntu-sdk-team/ppa - - sudo apt-get update - - sudo apt-get install cmake libsdl1.2-dev openjdk-7-jdk ant lib32z1-dev lib32stdc++6 - - git submodule update --init --recursive - - if [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then wget --timeout=30 http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 -O ndk.tar.bz2 && tar -xf ndk.tar.bz2; fi - - if [[ "$CXX" == *clang* ]]; then export NDK_TOOLCHAIN_VERSION=clang; fi - - export ANDROID_HOME=$(pwd)/android-ndk-r9 NDK=$(pwd)/android-ndk-r9 +matrix: + include: + - compiler: clang + env: PPSSPP_BUILD_TYPE=Linux + CMAKE=TRUE -before_script: - - mkdir build-travis - - cd build-travis - - cmake -DHEADLESS=ON .. - - cd .. +before_install: + - git submodule update --init --recursive + - sudo apt-get install aria2 -qq + - download_extract() { aria2c -x 16 $1 -o $2 && tar -xf $2; } +# Travis uses CMake 2.8.7. We require 2.8.8. Grab latest + - if [ "$CMAKE" == "TRUE" ]; then + sudo apt-get install lib32stdc++6 -qq && + aria2c -x 16 http://www.cmake.org/files/v2.8/cmake-2.8.12.1-Linux-i386.sh && + chmod a+x cmake-2.8.12.1-Linux-i386.sh && + sudo ./cmake-2.8.12.1-Linux-i386.sh --skip-license --prefix=/usr; + fi + +install: +# Linux Setup + - if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then + sudo apt-get install libsdl1.2-dev -qq; +# Android NDK + - elif [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then + NDK_VER=android-ndk-r9b && + sudo apt-get install ant -qq && + download_extract http://dl.google.com/android/ndk/${NDK_VER}-linux-x86_64.tar.bz2 ${NDK_VER}-linux-x86_64.tar.bz2 && + export ANDROID_HOME=$(pwd)/${NDK_VER} NDK=$(pwd)/${NDK_VER} && + if [[ "$CXX" == *clang* ]]; then export NDK_TOOLCHAIN_VERSION=clang; fi; +# Blackberry NDK: 10.2.0.1155 + - elif [ "$PPSSPP_BUILD_TYPE" == "Blackberry" ]; then + download_extract https://googledrive.com/host/0B5UBD4wjtpZ-QVdzSElobzNTOU0 libs.tar.gz && + download_extract https://googledrive.com/host/0B5UBD4wjtpZ-NV80UzFYMVRkSXM tools.tar.gz && + export QNX_TARGET="$(pwd)/target_10_2_0_1155/qnx6" QNX_HOST="$(pwd)/host_10_2_0_15/linux/x86" && PATH="$QNX_HOST/usr/bin:$PATH"; +# Symbian NDK: Belle + - elif [ "$PPSSPP_BUILD_TYPE" == "Symbian" ]; then + sudo apt-get install lib32stdc++6 lib32bz2-1.0 -qq && + download_extract https://googledrive.com/host/0B5UBD4wjtpZ-T0Iwa0F3b2JqREE ndk.tar.bz2 && + sed -i "s!/SDKs!$(pwd)/SDKs!" SDKs/SymbianSR1Qt474/bin/qt.conf && + cp ffmpeg/symbian/armv6/lib/* SDKs/SymbianSR1Qt474/epoc32/release/armv5/urel/ && + export EPOCROOT=$(pwd)/SDKs/SymbianSR1Qt474 SBS_GCCE463BIN=$(pwd)/tools/gcce4/bin && + PATH=$SBS_GCCE463BIN:$(pwd)/tools/sbs/bin:$EPOCROOT/epoc32/tools:$(pwd)/tools:$EPOCROOT/bin:$(pwd)/tools/sbs/linux-x86_64-libc2_15/bin:$PATH; + fi script: - - if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then cd build-travis && make && cd ..; else cd android && ./ab.sh && cd ..; fi - - if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then ./test.py; fi +# Compile PPSSPP + - if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then + ./b.sh --headless; + - elif [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then + pushd android && ./ab.sh && popd; + - elif [ "$PPSSPP_BUILD_TYPE" == "Blackberry" ]; then + ./b.sh --no-package; + - elif [ "$PPSSPP_BUILD_TYPE" == "Symbian" ]; then + pushd Qt && qmake -spec symbian-sbsv2 PPSSPPQt.pro && make release-gcce -j4 && make sis && popd; + fi -# For now, Android clang seems to be failing to build. -matrix: - exclude: - - compiler: clang - env: PPSSPP_BUILD_TYPE=Android +after_success: + - if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then ./test.py; fi diff --git a/Blackberry/bar-descriptor.xml b/Blackberry/bar-descriptor.xml index 64123f1788..7abea9c015 100644 --- a/Blackberry/bar-descriptor.xml +++ b/Blackberry/bar-descriptor.xml @@ -3,9 +3,9 @@ com.Qtness.PPSSPP PPSSPP PPSSPPBlackberry - 0.9.5 + 0.9.6 1 - Playstation portable emulator. + Playstation Portable emulator. Qtness gYAAgGE4qaHzBnzEAu8JKe4G1OI diff --git a/Blackberry/bb.toolchain.cmake b/Blackberry/bb.toolchain.cmake new file mode 100644 index 0000000000..381e3cf544 --- /dev/null +++ b/Blackberry/bb.toolchain.cmake @@ -0,0 +1,33 @@ +# Standard settings +set (CMAKE_SYSTEM_NAME QNX) +set (CMAKE_SYSTEM_VERSION 1) +set (CMAKE_PREFIX_PATH $ENV{QNX_TARGET}/usr) +set (CMAKE_INCLUDE_PATH $ENV{QNX_TARGET}/usr/include) +if (SIMULATOR) + set (CMAKE_SYSTEM_PROCESSOR x86) + set (CMAKE_LIBRARY_PATH $ENV{QNX_TARGET}/x86 $ENV{QNX_TARGET}/x86/usr) +else() + set (CMAKE_SYSTEM_PROCESSOR armv7) + set (CMAKE_LIBRARY_PATH $ENV{QNX_TARGET}/armle-v7 $ENV{QNX_TARGET}/armle-v7/usr) +endif() +set (UNIX True) + +set (CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_LIBRARY_PATH} CACHE string "Blackberry find search path root") +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +include (CMakeForceCompiler) +CMAKE_FORCE_C_COMPILER (nto${CMAKE_SYSTEM_PROCESSOR}-gcc nto${CMAKE_SYSTEM_PROCESSOR}-gcc) +CMAKE_FORCE_CXX_COMPILER (nto${CMAKE_SYSTEM_PROCESSOR}-g++ nto${CMAKE_SYSTEM_PROCESSOR}-g++) +set (CMAKE_COMPILER_IS_GNUCXX True) +execute_process( COMMAND nto${CMAKE_SYSTEM_PROCESSOR}-gcc --version +OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) +string( REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" GCC_VERSION "${GCC_VERSION}" ) +set (CMAKE_C_COMPILER_VERSION ${GCC_VERSION}) +set (CMAKE_CXX_COMPILER_VERSION ${GCC_VERSION}) + +# Skip the platform compiler checks for cross compiling +set (CMAKE_CROSSCOMPILING TRUE) +set (CMAKE_C_COMPILER_WORKS TRUE) +set (CMAKE_CXX_COMPILER_WORKS TRUE) + diff --git a/Blackberry/build.sh b/Blackberry/build.sh deleted file mode 100755 index 89d2c98423..0000000000 --- a/Blackberry/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -BB_OS=`cat ${QNX_TARGET}/etc/qversion 2>/dev/null` -if [ -z "$BB_OS" ]; then - echo "Could not find your Blackberry NDK. Please source bbndk-env.sh" - exit 1 -fi -echo "Building for Blackberry ${BB_OS}" - -# Set up cmake with GCC 4.6.3 cross-compiler from PATH -CC=ntoarmv7-gcc CXX=ntoarmv7-g++ cmake -DBLACKBERRY=${BB_OS} .. - -# Compile and create unsigned PPSSPP.bar with debugtoken -DEBUG="-devMode -debugToken ${HOME}/debugtoken.bar" -make -j4 && blackberry-nativepackager -package PPSSPP.bar bar-descriptor.xml $DEBUG diff --git a/CMakeLists.txt b/CMakeLists.txt index e86315f086..b95eef2db0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,13 +10,17 @@ if(ANDROID) endif() if(BLACKBERRY) - set(CMAKE_SYSTEM_NAME "QNX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS") endif() if (IOS OR BLACKBERRY) - set(ARM ON) - set(USE_FFMPEG ON) + if (SIMULATOR) + set(X86 ON) + else() + set(ARM ON) + set(ARMEABI_V7A ON) + set(USE_FFMPEG ON) + endif() endif() if (MAEMO) @@ -29,7 +33,7 @@ if(LOONGSON) set(MIPS ON) # MIPS + x86 for now endif() -if(ARM) +if(ARM OR SIMULATOR) set(USING_GLES2 ON) else() # Assume x86 set(X86 ON) @@ -64,26 +68,28 @@ option(IOS "Set to ON if targeting an iOS device" ${IOS}) option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2}) option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI}) option(HEADLESS "Set to OFF to not generate the PPSSPPHeadless target" ${HEADLESS}) +option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" ${SIMULATOR}) option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG}) -if(ANDROID) - if(NOT ANDROID_ABI) +if(ANDROID OR BLACKBERRY OR IOS) + if (NOT CMAKE_TOOLCHAIN_FILE) + if (ANDROID) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/android/android.toolchain.cmake) + elseif(BLACKBERRY) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/Blackberry/bb.toolchain.cmake) + elseif(IOS) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/ios/ios.toolchain.cmake) + endif() message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE was not set!\n" - "Delete the CMakeCache.txt file and CMakeFiles directory." - "Rerun ${CMAKE_COMMAND} with \"-DCMAKE_TOOLCHAIN_FILE" - "=${CMAKE_SOURCE_DIR}/android/android.toolchain.cmake\"") + "Delete the CMakeCache.txt file and CMakeFiles directory.\n" + "Re-run ${CMAKE_COMMAND} with:\n" + "\"-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}\"") endif() +endif() + +if(ANDROID) set(CoreLibName ppsspp_jni) set(CoreLinkType SHARED) -elseif(IOS) - if (NOT IOS_PLATFORM) - message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE was not set!\n" - "Delete the CMakeCache.txt file and CMakeFiles directory." - "Rerun ${CMAKE_COMMAND} with \"-DCMAKE_TOOLCHAIN_FILE" - "=${CMAKE_SOURCE_DIR}/ios/ios.toolchain.cmake\"") - endif() - set(CoreLibName Core) - set(CoreLinkType STATIC) else() set(CoreLibName Core) set(CoreLinkType STATIC) @@ -149,7 +155,7 @@ if(NOT MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp") endif() if(NOT APPLE) - if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") + if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") add_definitions(-Wno-psabi) endif() add_definitions(-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE=1) @@ -160,7 +166,10 @@ if(NOT MSVC) endif() if(BLACKBERRY) - add_definitions(-D_QNX_SOURCE -DARMV7 -O3 -mfpu=neon -mtune=cortex-a9) + add_definitions(-D_QNX_SOURCE) + if(ARM) + add_definitions(-DARMV7 -O3 -mfpu=neon -mcpu=cortex-a9) + endif() endif() if(X86 AND NOT MIPS) @@ -259,8 +268,6 @@ add_library(Common STATIC Common/KeyMap.h Common/LogManager.cpp Common/LogManager.h - Common/MathUtil.cpp - Common/MathUtil.h Common/MemArena.cpp Common/MemArena.h Common/MemoryUtil.cpp @@ -270,8 +277,6 @@ add_library(Common STATIC Common/MsgHandler.h Common/StringUtils.cpp Common/StringUtils.h - Common/Thread.cpp - Common/Thread.h Common/ThreadPools.cpp Common/ThreadPools.h Common/Timer.cpp @@ -283,8 +288,175 @@ if(WIN32) target_link_libraries(Common winmm) endif() -if(BLACKBERRY) - set(LIBZIP z) +if(NOT USING_GLES2) + include_directories(${OPENGL_INCLUDE_DIR}) + + add_definitions(-DGLEW_STATIC) + add_library(glew STATIC + native/ext/glew/GL/glew.h + native/ext/glew/GL/glxew.h + native/ext/glew/GL/wglew.h + native/ext/glew/glew.c) + target_link_libraries(glew ${OPENGL_LIBRARIES}) + include_directories(native/ext/glew) + set(GLEW_LIBRARIES glew) +endif() + +add_library(snappy STATIC + ext/snappy/snappy-c.cpp + ext/snappy/snappy-internal.h + ext/snappy/snappy-sinksource.h + ext/snappy/snappy-stubs-internal.h + ext/snappy/snappy-stubs-public.h + ext/snappy/snappy.cpp + ext/snappy/snappy.h +) +include_directories(ext/snappy) + +add_library(vjson STATIC + native/ext/vjson/json.cpp + native/ext/vjson/json.h + native/ext/vjson/block_allocator.cpp + native/ext/vjson/block_allocator.h +) + +add_library(rg_etc1 STATIC + native/ext/rg_etc1/rg_etc1.cpp + native/ext/rg_etc1/rg_etc1.h) +include_directories(native/ext/rg_etc1) + +add_library(stb_vorbis STATIC + native/ext/stb_vorbis/stb_vorbis.c + native/ext/stb_vorbis/stb_vorbis.h) +include_directories(native/ext/stb_vorbis) + +if(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) + if(BLACKBERRY) + set(PLATFORM_ARCH "blackberry/armv7") + elseif(IOS) + set(PLATFORM_ARCH "ios/universal") + elseif(MACOSX) + set(PLATFORM_ARCH "macosx/x86_64") + elseif(LINUX) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PLATFORM_ARCH "linux/x86_64") + else() + set(PLATFORM_ARCH "linux/x86") + endif() + endif() + # Using static libraries + if (DEFINED PLATFORM_ARCH) + include_directories(ffmpeg/${PLATFORM_ARCH}/include) + link_directories(ffmpeg/${PLATFORM_ARCH}/lib) + set(FFMPEG_LIBRARIES libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a) + else() + # Manual definition of system library locations by the user. + if (DEFINED FFMPEG_INCLUDE_PATH) + include_directories(ffmpeg ${FFMPEG_INCLUDE_PATH}) + endif() + if (DEFINED AVFORMAT_PATH) + add_library(libavformat STATIC IMPORTED) + set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${AVFORMAT_PATH}) + SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavformat) + endif() + if (DEFINED AVCODEC_PATH) + add_library(libavcodec STATIC IMPORTED) + set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${AVCODEC_PATH}) + SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavcodec) + endif() + if (DEFINED AVUTIL_PATH) + add_library(libavutil STATIC IMPORTED) + set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${AVUTIL_PATH}) + SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavutil) + endif() + if (DEFINED SWRESAMPLE_PATH) + add_library(libswresample STATIC IMPORTED) + set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${SWRESAMPLE_PATH}) + SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswresample) + endif() + if (DEFINED SWSCALE_PATH) + add_library(libswscale STATIC IMPORTED) + set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${SWSCALE_PATH}) + SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswscale) + endif() + endif(DEFINED PLATFORM_ARCH) +endif(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) + +if(USE_FFMPEG) + # Using shared libraries + if(DEFINED FFMPEG_BUILDDIR) + include_directories(ffmpeg ${FFMPEG_BUILDDIR}) + + add_library(libavformat STATIC IMPORTED) + set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavformat/libavformat.a) + add_library(libavcodec STATIC IMPORTED) + set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavcodec/libavcodec.a) + add_library(libavutil STATIC IMPORTED) + set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavutil/libavutil.a) + add_library(libswresample STATIC IMPORTED) + set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswresample/libswresample.a) + add_library(libswscale STATIC IMPORTED) + set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswscale/libswscale.a) + + SET (FFMPEG_LIBRARIES + libavformat + libavcodec + libavutil + libswresample + libswscale + ) + endif() + + if(IOS OR BLACKBERRY) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} iconv) + endif() + + if(APPLE) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} bz2 "-framework CoreVideo") + if (NOT IOS) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} "-framework VideoDecodeAcceleration") + endif() + endif(APPLE) + + set(LinkCommon ${LinkCommon} ${FFMPEG_LIBRARIES}) + add_definitions(-DUSE_FFMPEG) +endif(USE_FFMPEG) + +# Modification to show where we are pulling the ffmpeg libraries from. +if(USE_FFMPEG AND DEFINED FFMPEG_LIBRARIES) + target_link_libraries(Common ${FFMPEG_LIBRARIES}) + message(STATUS "FFMPEG library locations:") + if(DEFINED PLATFORM_ARCH) + set(TEMP ${CMAKE_SOURCE_DIR}/ffmpeg/${PLATFORM_ARCH}/lib) + message(STATUS "libavcodec location: ${TEMP}/libavcodec.a") + message(STATUS "libavformat location: ${TEMP}/libavformat.a") + message(STATUS "libavutil location: ${TEMP}/libavutil.a") + message(STATUS "libswresample location: ${TEMP}/libswresample.a") + message(STATUS "libswscale location: ${TEMP}/libswscale.a") + else() + get_target_property(TEMP libavcodec IMPORTED_LOCATION) + message(STATUS "libavcodec location: ${TEMP}") + get_target_property(TEMP libavformat IMPORTED_LOCATION) + message(STATUS "libavformat location: ${TEMP}") + get_target_property(TEMP libavutil IMPORTED_LOCATION) + message(STATUS "libavutil location: ${TEMP}") + get_target_property(TEMP libswresample IMPORTED_LOCATION) + message(STATUS "libswresample location: ${TEMP}") + get_target_property(TEMP libswscale IMPORTED_LOCATION) + message(STATUS "libswscale location: ${TEMP}") + endif(DEFINED PLATFORM_ARCH) +else() + message(STATUS "ERROR: No FFMPEG library locations") +endif() + +if(USE_FFMPEG AND NOT DEFINED FFMPEG_LIBRARIES) + message(WARNING "FFMPEG_BUILDDIR variable or manual path definition is required to enable FFmpeg. Disabling it.") + unset(USE_FFMPEG) +endif() + +find_package(ZLIB) +if(ZLIB_FOUND) + include_directories(${ZLIB_INCLUDE_DIR}) else() add_library(zlib STATIC ext/zlib/adler32.c @@ -316,111 +488,113 @@ else() ext/zlib/zutil.h ) include_directories(ext/zlib) - set(LIBZIP zlib) + set(ZLIB_LIBRARY zlib) endif() -add_library(snappy STATIC - ext/snappy/snappy-c.cpp - ext/snappy/snappy-internal.h - ext/snappy/snappy-sinksource.h - ext/snappy/snappy-stubs-internal.h - ext/snappy/snappy-stubs-public.h - ext/snappy/snappy.cpp - ext/snappy/snappy.h +add_library(cityhash STATIC + native/ext/cityhash/city.cpp + native/ext/cityhash/city.h + native/ext/cityhash/citycrc.h ) -include_directories(ext/snappy) +include_directories(ext/cityhash) -add_library(rg_etc1 STATIC - native/ext/rg_etc1/rg_etc1.cpp - native/ext/rg_etc1/rg_etc1.h) -include_directories(native/ext/rg_etc1) +add_library(libzip STATIC + native/ext/libzip/zip.h + native/ext/libzip/mkstemp.c + native/ext/libzip/zip_add.c + native/ext/libzip/zip_add_dir.c + native/ext/libzip/zip_close.c + native/ext/libzip/zip_delete.c + native/ext/libzip/zip_dirent.c + native/ext/libzip/zip_entry_free.c + native/ext/libzip/zip_entry_new.c + native/ext/libzip/zip_err_str.c + native/ext/libzip/zip_error.c + native/ext/libzip/zip_error_clear.c + native/ext/libzip/zip_error_get.c + native/ext/libzip/zip_error_get_sys_type.c + native/ext/libzip/zip_error_strerror.c + native/ext/libzip/zip_error_to_str.c + native/ext/libzip/zip_fclose.c + native/ext/libzip/zip_file_error_clear.c + native/ext/libzip/zip_file_error_get.c + native/ext/libzip/zip_file_get_offset.c + native/ext/libzip/zip_file_strerror.c + native/ext/libzip/zip_filerange_crc.c + native/ext/libzip/zip_fopen.c + native/ext/libzip/zip_fopen_index.c + native/ext/libzip/zip_fread.c + native/ext/libzip/zip_free.c + native/ext/libzip/zip_get_archive_comment.c + native/ext/libzip/zip_get_archive_flag.c + native/ext/libzip/zip_get_file_comment.c + native/ext/libzip/zip_get_name.c + native/ext/libzip/zip_get_num_files.c + native/ext/libzip/zip_memdup.c + native/ext/libzip/zip_name_locate.c + native/ext/libzip/zip_new.c + native/ext/libzip/zip_open.c + native/ext/libzip/zip_rename.c + native/ext/libzip/zip_replace.c + native/ext/libzip/zip_set_archive_comment.c + native/ext/libzip/zip_set_archive_flag.c + native/ext/libzip/zip_set_file_comment.c + native/ext/libzip/zip_set_name.c + native/ext/libzip/zip_source_buffer.c + native/ext/libzip/zip_source_file.c + native/ext/libzip/zip_source_filep.c + native/ext/libzip/zip_source_free.c + native/ext/libzip/zip_source_function.c + native/ext/libzip/zip_source_zip.c + native/ext/libzip/zip_stat.c + native/ext/libzip/zip_stat_index.c + native/ext/libzip/zip_stat_init.c + native/ext/libzip/zip_strerror.c + native/ext/libzip/zip_unchange.c + native/ext/libzip/zip_unchange_all.c + native/ext/libzip/zip_unchange_archive.c + native/ext/libzip/zip_unchange_data.c) +target_link_libraries(libzip ${ZLIB_LIBRARY}) +include_directories(native/ext/libzip) +set(LIBZIP_LIBRARY libzip) -if(NOT USING_GLES2) - include_directories(${OPENGL_INCLUDE_DIR}) - - add_definitions(-DGLEW_STATIC) - add_library(glew STATIC - native/ext/glew/GL/glew.h - native/ext/glew/GL/glxew.h - native/ext/glew/GL/wglew.h - native/ext/glew/glew.c) - target_link_libraries(glew ${OPENGL_LIBRARIES}) - include_directories(native/ext/glew) - set(GLEW_LIBRARIES glew) +# FindPNG does a few things we don't want. So do it ourselves. +# Fixed to libpng16, otherwise it can pick up earlier even if newer exists. +find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng16/png.h") +find_library(PNG_LIBRARY NAMES png16 libpng16 ) +find_package(PackageHandleStandardArgs) +find_package_handle_standard_args(PNG REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR) +if (PNG_FOUND) + include_directories(${PNG_PNG_INCLUDE_DIR}) +else() + add_library(png16 STATIC + native/ext/libpng16/pngconf.h + native/ext/libpng16/pngdebug.h + native/ext/libpng16/png.c + native/ext/libpng16/png.h + native/ext/libpng16/pngerror.c + native/ext/libpng16/pngget.c + native/ext/libpng16/pnginfo.h + native/ext/libpng16/pnglibconf.h + native/ext/libpng16/pngmem.c + native/ext/libpng16/pngpread.c + native/ext/libpng16/pngpriv.h + native/ext/libpng16/pngread.c + native/ext/libpng16/pngrio.c + native/ext/libpng16/pngrtran.c + native/ext/libpng16/pngrutil.c + native/ext/libpng16/pngset.c + native/ext/libpng16/pngstruct.h + native/ext/libpng16/pngtest.c + native/ext/libpng16/pngtrans.c + native/ext/libpng16/pngwio.c + native/ext/libpng16/pngwrite.c + native/ext/libpng16/pngwtran.c + native/ext/libpng16/pngwutil.c) + set(PNG_LIBRARY png16) + include_directories(native/ext) endif() - -add_library(stb_image STATIC - native/ext/stb_image/stb_image.c - native/ext/stb_image/stb_image.h) -include_directories(native/ext/stb_image) - -add_library(stb_vorbis STATIC - native/ext/stb_vorbis/stb_vorbis.c - native/ext/stb_vorbis/stb_vorbis.h) -include_directories(native/ext/stb_vorbis) - -if(ANDROID) - add_library(libzip STATIC - native/ext/libzip/zip.h - native/ext/libzip/mkstemp.c - native/ext/libzip/zip_add.c - native/ext/libzip/zip_add_dir.c - native/ext/libzip/zip_close.c - native/ext/libzip/zip_delete.c - native/ext/libzip/zip_dirent.c - native/ext/libzip/zip_entry_free.c - native/ext/libzip/zip_entry_new.c - native/ext/libzip/zip_err_str.c - native/ext/libzip/zip_error.c - native/ext/libzip/zip_error_clear.c - native/ext/libzip/zip_error_get.c - native/ext/libzip/zip_error_get_sys_type.c - native/ext/libzip/zip_error_strerror.c - native/ext/libzip/zip_error_to_str.c - native/ext/libzip/zip_fclose.c - native/ext/libzip/zip_file_error_clear.c - native/ext/libzip/zip_file_error_get.c - native/ext/libzip/zip_file_get_offset.c - native/ext/libzip/zip_file_strerror.c - native/ext/libzip/zip_filerange_crc.c - native/ext/libzip/zip_fopen.c - native/ext/libzip/zip_fopen_index.c - native/ext/libzip/zip_fread.c - native/ext/libzip/zip_free.c - native/ext/libzip/zip_get_archive_comment.c - native/ext/libzip/zip_get_archive_flag.c - native/ext/libzip/zip_get_file_comment.c - native/ext/libzip/zip_get_name.c - native/ext/libzip/zip_get_num_files.c - native/ext/libzip/zip_memdup.c - native/ext/libzip/zip_name_locate.c - native/ext/libzip/zip_new.c - native/ext/libzip/zip_open.c - native/ext/libzip/zip_rename.c - native/ext/libzip/zip_replace.c - native/ext/libzip/zip_set_archive_comment.c - native/ext/libzip/zip_set_archive_flag.c - native/ext/libzip/zip_set_file_comment.c - native/ext/libzip/zip_set_name.c - native/ext/libzip/zip_source_buffer.c - native/ext/libzip/zip_source_file.c - native/ext/libzip/zip_source_filep.c - native/ext/libzip/zip_source_free.c - native/ext/libzip/zip_source_function.c - native/ext/libzip/zip_source_zip.c - native/ext/libzip/zip_stat.c - native/ext/libzip/zip_stat_index.c - native/ext/libzip/zip_stat_init.c - native/ext/libzip/zip_strerror.c - native/ext/libzip/zip_unchange.c - native/ext/libzip/zip_unchange_all.c - native/ext/libzip/zip_unchange_archive.c - native/ext/libzip/zip_unchange_data.c) - target_link_libraries(libzip zlib) - include_directories(native/ext/libzip) - set(LIBZIP libzip zlib) -endif() - + set(nativeExtra) set(nativeExtraLibs) if(ANDROID) @@ -468,7 +642,10 @@ elseif(SDL_FOUND) set(TargetBin PPSSPPSDL) # Require SDL include_directories(${SDL_INCLUDE_DIR}) - set(nativeExtra ${nativeExtra} native/base/PCMain.cpp) + set(nativeExtra ${nativeExtra} + SDL/SDLJoystick.h + SDL/SDLJoystick.cpp + native/base/PCMain.cpp) set(nativeExtraLibs ${nativeExtraLibs} ${SDL_LIBRARY}) if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) @@ -517,6 +694,10 @@ add_library(native STATIC native/base/timeutil.h native/data/compression.cpp native/data/compression.h + native/ext/vjson/json.cpp + native/ext/vjson/json.h + native/ext/vjson/block_allocator.cpp + native/ext/vjson/block_allocator.h native/file/chunk_file.cpp native/file/chunk_file.h native/file/dialog.cpp @@ -529,6 +710,8 @@ add_library(native STATIC native/file/file_util.h native/file/ini_file.cpp native/file/ini_file.h + native/file/path.cpp + native/file/path.h native/file/vfs.h native/file/zip_read.cpp native/file/zip_read.h @@ -630,13 +813,15 @@ add_library(native STATIC native/util/random/rng.h native/util/text/utf8.h native/util/text/utf8.cpp + native/util/text/parsers.h + native/util/text/parsers.cpp native/util/const_map.h native/ext/jpge/jpgd.cpp native/ext/jpge/jpgd.h native/ext/jpge/jpge.cpp native/ext/jpge/jpge.h) include_directories(native) -target_link_libraries(native ${LIBZIP} rg_etc1 stb_image stb_vorbis snappy ${GLEW_LIBRARIES}) +target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARY} rg_etc1 vjson stb_vorbis snappy ${GLEW_LIBRARIES}) if(ANDROID) target_link_libraries(native log) @@ -681,12 +866,15 @@ if(ARM) Core/MIPS/ARM/ArmCompFPU.cpp Core/MIPS/ARM/ArmCompLoadStore.cpp Core/MIPS/ARM/ArmCompVFPU.cpp + Core/MIPS/ARM/ArmCompVFPUNEON.cpp Core/MIPS/ARM/ArmJit.cpp Core/MIPS/ARM/ArmJit.h Core/MIPS/ARM/ArmRegCache.cpp Core/MIPS/ARM/ArmRegCache.h Core/MIPS/ARM/ArmRegCacheFPU.cpp Core/MIPS/ARM/ArmRegCacheFPU.h + GPU/GLES/VertexDecoderArm.cpp + GPU/GLES/VertexDecoder.h ext/disarm.cpp) elseif(X86) set(CoreExtra ${CoreExtra} @@ -703,6 +891,8 @@ elseif(X86) Core/MIPS/x86/RegCache.h Core/MIPS/x86/RegCacheFPU.cpp Core/MIPS/x86/RegCacheFPU.h + GPU/GLES/VertexDecoderX86.cpp + GPU/GLES/VertexDecoder.h ext/disarm.cpp) endif() @@ -849,6 +1039,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/sceNet.h Core/HLE/sceNetAdhoc.cpp Core/HLE/sceNetAdhoc.h + Core/HLE/proAdhoc.h + Core/HLE/proAdhoc.cpp Core/HLE/sceOpenPSID.cpp Core/HLE/sceOpenPSID.h Core/HLE/sceP3da.cpp @@ -946,6 +1138,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/SaveState.h Core/System.cpp Core/System.h + Core/Util/GameManager.cpp + Core/Util/GameManager.h Core/Util/BlockAllocator.cpp Core/Util/BlockAllocator.h Core/Util/PPGeDraw.cpp @@ -955,7 +1149,7 @@ add_library(${CoreLibName} ${CoreLinkType} $ Globals.h git-version.cpp) -target_link_libraries(${CoreLibName} Common native kirk xbrz xxhash +target_link_libraries(${CoreLibName} Common native kirk cityhash xbrz xxhash ${CoreExtraLibs} ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES}) setup_target_project(${CoreLibName} Core) @@ -970,7 +1164,7 @@ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/git-version.cpp PROPERTIES GENERATED TRUE) add_dependencies(${CoreLibName} GitVersion) -if(BLACKBERRY OR IOS OR ARMEABI_V7A) +if(ARMEABI_V7A) set(GPU_NEON GPU/Common/TextureDecoderNEON.cpp) endif() add_library(GPU OBJECT @@ -1006,6 +1200,7 @@ add_library(GPU OBJECT GPU/GLES/TextureScaler.h GPU/GLES/TransformPipeline.cpp GPU/GLES/TransformPipeline.h + GPU/GLES/SoftwareTransform.cpp GPU/GLES/VertexDecoder.cpp GPU/GLES/VertexDecoder.h GPU/GLES/VertexShaderGenerator.cpp @@ -1126,7 +1321,9 @@ set(NativeAppSource UI/UIShader.cpp UI/OnScreenDisplay.cpp UI/ControlMappingScreen.cpp + UI/Store.cpp UI/CwCheatScreen.cpp + UI/InstallZipScreen.cpp UI/ui_atlas.cpp) if(ANDROID AND ARM) set(NativeAppSource ${NativeAppSource} android/jni/ArmEmitterTest.cpp) @@ -1135,129 +1332,10 @@ set(NativeAssets android/assets/ui_atlas.zim assets/shaders assets/ppge_atlas.zim - assets/langregion.ini) + assets/langregion.ini + assets/unknown.png) set(LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT} ${nativeExtraLibs}) -if(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) - if(BLACKBERRY) - set(PLATFORM_ARCH "blackberry/armv7") - elseif(IOS) - set(PLATFORM_ARCH "ios/universal") - elseif(MACOSX) - set(PLATFORM_ARCH "macosx/x86_64") - elseif(LINUX) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PLATFORM_ARCH "linux/x86_64") - else() - set(PLATFORM_ARCH "linux/x86") - endif() - endif() - # Using static libraries - if (DEFINED PLATFORM_ARCH) - include_directories(ffmpeg/${PLATFORM_ARCH}/include) - link_directories(ffmpeg/${PLATFORM_ARCH}/lib) - set(FFMPEG_LIBRARIES libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a) - else() - # Manual definition of system library locations by the user. - if (DEFINED FFMPEG_INCLUDE_PATH) - include_directories(ffmpeg ${FFMPEG_INCLUDE_PATH}) - endif() - if (DEFINED AVFORMAT_PATH) - add_library(libavformat STATIC IMPORTED) - set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${AVFORMAT_PATH}) - SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavformat) - endif() - if (DEFINED AVCODEC_PATH) - add_library(libavcodec STATIC IMPORTED) - set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${AVCODEC_PATH}) - SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavcodec) - endif() - if (DEFINED AVUTIL_PATH) - add_library(libavutil STATIC IMPORTED) - set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${AVUTIL_PATH}) - SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavutil) - endif() - if (DEFINED SWRESAMPLE_PATH) - add_library(libswresample STATIC IMPORTED) - set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${SWRESAMPLE_PATH}) - SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswresample) - endif() - if (DEFINED SWSCALE_PATH) - add_library(libswscale STATIC IMPORTED) - set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${SWSCALE_PATH}) - SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswscale) - endif() - endif(DEFINED PLATFORM_ARCH) -endif(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) - -if(USE_FFMPEG) - # Using shared libraries - if(DEFINED FFMPEG_BUILDDIR) - include_directories(ffmpeg ${FFMPEG_BUILDDIR}) - - add_library(libavformat STATIC IMPORTED) - set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavformat/libavformat.a) - add_library(libavcodec STATIC IMPORTED) - set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavcodec/libavcodec.a) - add_library(libavutil STATIC IMPORTED) - set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavutil/libavutil.a) - add_library(libswresample STATIC IMPORTED) - set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswresample/libswresample.a) - add_library(libswscale STATIC IMPORTED) - set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswscale/libswscale.a) - - SET (FFMPEG_LIBRARIES - libavformat - libavcodec - libavutil - libswresample - libswscale - ) - endif() - - if(IOS OR BLACKBERRY) - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} iconv) - endif() - - if(APPLE) - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} bz2 "-framework CoreVideo") - if (NOT IOS) - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} "-framework VideoDecodeAcceleration") - endif() - endif(APPLE) - - set(LinkCommon ${LinkCommon} ${FFMPEG_LIBRARIES}) - add_definitions(-DUSE_FFMPEG) -endif(USE_FFMPEG) - -# Modification to show where we are pulling the ffmpeg libraries from. -if(USE_FFMPEG AND DEFINED FFMPEG_LIBRARIES) - target_link_libraries(Common ${FFMPEG_LIBRARIES}) - message(STATUS "FFMPEG library locations:") - if(DEFINED PLATFORM_ARCH) - set(TEMP ${CMAKE_SOURCE_DIR}/ffmpeg/${PLATFORM_ARCH}/lib) - message(STATUS "libavcodec location: ${TEMP}/libavcodec.a") - message(STATUS "libavformat location: ${TEMP}/libavformat.a") - message(STATUS "libavutil location: ${TEMP}/libavutil.a") - message(STATUS "libswresample location: ${TEMP}/libswresample.a") - message(STATUS "libswscale location: ${TEMP}/libswscale.a") - else() - get_target_property(TEMP libavcodec IMPORTED_LOCATION) - message(STATUS "libavcodec location: ${TEMP}") - get_target_property(TEMP libavformat IMPORTED_LOCATION) - message(STATUS "libavformat location: ${TEMP}") - get_target_property(TEMP libavutil IMPORTED_LOCATION) - message(STATUS "libavutil location: ${TEMP}") - get_target_property(TEMP libswresample IMPORTED_LOCATION) - message(STATUS "libswresample location: ${TEMP}") - get_target_property(TEMP libswscale IMPORTED_LOCATION) - message(STATUS "libswscale location: ${TEMP}") - endif(DEFINED PLATFORM_ARCH) -endif() -if(USE_FFMPEG AND NOT DEFINED FFMPEG_LIBRARIES) - message(WARNING "FFMPEG_BUILDDIR variable or manual path definition is required to enable FFmpeg. Disabling it.") - unset(USE_FFMPEG) -endif() if(HEADLESS) add_executable(PPSSPPHeadless @@ -1282,7 +1360,7 @@ endif() # installs file(INSTALL ${NativeAssets} DESTINATION assets) -file(INSTALL flash0 lang DESTINATION .) +file(INSTALL flash0 lang DESTINATION assets) # Fix CMake some Xcode settings. if(APPLE) @@ -1297,8 +1375,11 @@ if(APPLE) set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG") # These can be fast even for debug. + set_target_properties(cityhash PROPERTIES COMPILE_FLAGS "-O3") set_target_properties(snappy PROPERTIES COMPILE_FLAGS "-O3") - set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-O3") + if(NOT ZLIB_FOUND) + set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-O3") + endif() endif() if(APPLE AND NOT IOS) @@ -1311,10 +1392,6 @@ if(IOS) file(GLOB IOSAssets ios/assets/*.png) file(INSTALL ${IOSAssets} DESTINATION assets) - file(INSTALL assets/langregion.ini DESTINATION assets) - file(INSTALL assets/shaders DESTINATION assets) - file(INSTALL flash0 DESTINATION assets) - file(INSTALL lang DESTINATION assets) if (IOS_DEBUG) file(INSTALL pspautotests DESTINATION assets) endif() diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp index 90f8cbac0f..e7cc4308fe 100644 --- a/Common/ArmCPUDetect.cpp +++ b/Common/ArmCPUDetect.cpp @@ -24,7 +24,7 @@ #endif // Only Linux platforms have /proc/cpuinfo -#if !defined(BLACKBERRY) && !defined(IOS) && !defined(__SYMBIAN32__) +#if defined(__linux__) const char procfile[] = "/proc/cpuinfo"; // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu const char syscpupresentfile[] = "/sys/devices/system/cpu/present"; @@ -200,7 +200,7 @@ void CPUInfo::Detect() vendor = VENDOR_ARM; // Get the information about the CPU -#if defined(__SYMBIAN32__) || defined(BLACKBERRY) || defined(IOS) +#if !defined(__linux__) bool isVFP3 = false; bool isVFP4 = false; #ifdef IOS @@ -209,7 +209,7 @@ void CPUInfo::Detect() #ifdef __ARM_ARCH_7S__ isVFP4 = true; #endif - strcpy(brand_string, "Apple"); + strcpy(brand_string, "Apple A"); num_cores = 2; #elif defined(BLACKBERRY) isVFP3 = true; @@ -220,10 +220,14 @@ void CPUInfo::Detect() if (!strncmp(brand_string, "MSM", 3)) isVFP4 = true; deviceinfo_free_details(&details); -#elif defined(SYMBIAN) +#elif defined(__SYMBIAN32__) strcpy(brand_string, "Samsung ARMv6"); num_cores = 1; +#else + strcpy(brand_string, "Unknown"); + num_cores = 1; #endif + strncpy(cpu_string, brand_string, sizeof(cpu_string)); // Hardcode this for now bSwp = true; bHalf = true; @@ -240,7 +244,7 @@ void CPUInfo::Detect() bIDIVt = isVFP4; bFP = false; bASIMD = false; -#else +#else // __linux__ strncpy(cpu_string, GetCPUString(), sizeof(cpu_string)); bSwp = CheckCPUFeature("swp"); bHalf = CheckCPUFeature("half"); @@ -255,46 +259,36 @@ void CPUInfo::Detect() bVFPv4 = CheckCPUFeature("vfpv4"); bIDIVa = CheckCPUFeature("idiva"); bIDIVt = CheckCPUFeature("idivt"); - // Qualcomm Krait supports IDIVA but it doesn't report it. Check for krait. - if (GetCPUImplementer() == 0x51 && GetCPUPart() == 0x6F) // Krait(300) is 0x6F, Scorpion is 0x4D + // Qualcomm Krait supports IDIVA but it doesn't report it. Check for krait (0x4D = Plus, 0x6F = Pro). + unsigned short CPUPart = GetCPUPart(); + if (GetCPUImplementer() == 0x51 && (CPUPart == 0x4D || CPUPart == 0x6F)) bIDIVa = bIDIVt = true; // These two require ARMv8 or higher bFP = CheckCPUFeature("fp"); bASIMD = CheckCPUFeature("asimd"); num_cores = GetCoreCount(); #endif -// On android, we build a separate library for ARMv7 so this is fine. -// TODO: Check for ARMv7 on other platforms. -#if defined(__ARM_ARCH_7A__) - bArmV7 = true; -#else - bArmV7 = false; -#endif } // Turn the cpu info into a string we can show std::string CPUInfo::Summarize() { std::string sum; -#if defined(BLACKBERRY) || defined(IOS) || defined(__SYMBIAN32__) - sum = StringFromFormat("%i cores", num_cores); -#else if (num_cores == 1) sum = StringFromFormat("%s, %i core", cpu_string, num_cores); else sum = StringFromFormat("%s, %i cores", cpu_string, num_cores); -#endif if (bSwp) sum += ", SWP"; if (bHalf) sum += ", Half"; if (bThumb) sum += ", Thumb"; if (bFastMult) sum += ", FastMult"; - if (bVFP) sum += ", VFP"; if (bEDSP) sum += ", EDSP"; if (bThumbEE) sum += ", ThumbEE"; - if (bNEON) sum += ", NEON"; - if (bVFPv3) sum += ", VFPv3"; if (bTLS) sum += ", TLS"; + if (bVFP) sum += ", VFP"; + if (bVFPv3) sum += ", VFPv3"; if (bVFPv4) sum += ", VFPv4"; + if (bNEON) sum += ", NEON"; if (bIDIVa) sum += ", IDIVa"; if (bIDIVt) sum += ", IDIVt"; diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 9ea055887c..fc322b273c 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -18,6 +18,8 @@ #include "ArmEmitter.h" #include "CPUDetect.h" +#include "base/logging.h" + #include #include #include @@ -36,6 +38,12 @@ #include #endif +// __FUNCTION__ is misused a lot below, it's no longer a string literal but a virtual +// variable so this use fails in some compilers. Just define it away for now. +#ifndef _MSC_VER +#define __FUNCTION__ "(n/a)" +#endif + namespace ArmGen { @@ -87,6 +95,10 @@ Operand2 AssumeMakeOperand2(u32 imm) { Operand2 op2; bool result = TryMakeOperand2(imm, op2); _dbg_assert_msg_(JIT, result, "Could not make assumed Operand2."); + if (!result) { + // Make double sure that we get it logged. + ERROR_LOG(JIT, "Could not make assumed Operand2."); + } return op2; } @@ -148,6 +160,11 @@ void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg, bool negate) void ARMXEmitter::ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) { + if (val == 0) { + if (rd != rs) + MOV(rd, rs); + return; + } Operand2 op2; bool negated; if (TryMakeOperand2_AllowNegation(val, op2, &negated)) { @@ -162,8 +179,8 @@ void ARMXEmitter::ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) // Decompose into two additions. ADD(rd, rs, Operand2((u8)(val >> 8), 12)); // rotation right by 12*2 == rotation left by 8 ADD(rd, rd, Operand2((u8)(val), 0)); - } else if (((-(u32)(s32)val) & 0xFFFF0000) == 0) { - val = -(u32)(s32)val; + } else if ((((u32)-(s32)val) & 0xFFFF0000) == 0) { + val = (u32)-(s32)val; SUB(rd, rs, Operand2((u8)(val >> 8), 12)); SUB(rd, rd, Operand2((u8)(val), 0)); } else { @@ -189,7 +206,7 @@ void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) } else { int ops = 0; for (int i = 0; i < 32; i += 2) { - u8 bits = (val >> i) & 0xFF; + u8 bits = RotR(val, i) & 0xFF; // If either low bit is not set, we need to use a BIC for them. if ((bits & 3) != 3) { ++ops; @@ -198,10 +215,16 @@ void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) } // The worst case is 4 (e.g. 0x55555555.) - if (ops <= 3 || !cpu_info.bArmV7) { +#ifdef HAVE_ARMV7 + if (ops > 3) { + MOVI2R(scratch, val); + AND(rd, rs, scratch); + } else +#endif + { bool first = true; for (int i = 0; i < 32; i += 2) { - u8 bits = (val >> i) & 0xFF; + u8 bits = RotR(val, i) & 0xFF; if ((bits & 3) != 3) { u8 rotation = i == 0 ? 0 : 16 - i / 2; if (first) { @@ -214,9 +237,6 @@ void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) i += 8 - 2; } } - } else { - MOVI2R(scratch, val); - AND(rd, rs, scratch); } } } @@ -250,12 +270,17 @@ void ARMXEmitter::TSTI2R(ARMReg rs, u32 val, ARMReg scratch) void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) { Operand2 op2; - if (TryMakeOperand2(val, op2)) { + if (val == 0) { + // Avoid the ALU, may improve pipeline. + if (rd != rs) { + MOV(rd, rs); + } + } else if (TryMakeOperand2(val, op2)) { ORR(rd, rs, op2); } else { int ops = 0; for (int i = 0; i < 32; i += 2) { - u8 bits = (val >> i) & 0xFF; + u8 bits = RotR(val, i) & 0xFF; // If either low bit is set, we need to use a ORR for them. if ((bits & 3) != 0) { ++ops; @@ -268,10 +293,15 @@ void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) if (TryMakeOperand2_AllowInverse(val, op2, &inversed) && ops >= 3) { MVN(scratch, op2); ORR(rd, rs, scratch); - } else if (ops <= 3 || !cpu_info.bArmV7) { +#ifdef HAVE_ARMV7 + } else if (ops > 3) { + MOVI2R(scratch, val); + ORR(rd, rs, scratch); +#endif + } else { bool first = true; for (int i = 0; i < 32; i += 2) { - u8 bits = (val >> i) & 0xFF; + u8 bits = RotR(val, i) & 0xFF; if ((bits & 3) != 0) { u8 rotation = i == 0 ? 0 : 16 - i / 2; if (first) { @@ -284,9 +314,6 @@ void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) i += 8 - 2; } } - } else { - MOVI2R(scratch, val); - ORR(rd, rs, scratch); } } } @@ -329,26 +356,48 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize) Operand2 op2; bool inverse; - if (cpu_info.bArmV7 && !optimize) +#ifdef HAVE_ARMV7 + // Unused + if (!optimize) { // For backpatching on ARMv7 MOVW(reg, val & 0xFFFF); MOVT(reg, val, true); + return; } - else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) { +#endif + + if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) { inverse ? MVN(reg, op2) : MOV(reg, op2); } else { - if (cpu_info.bArmV7) - { - // Use MOVW+MOVT for ARMv7+ - MOVW(reg, val & 0xFFFF); - if(val & 0xFFFF0000) - MOVT(reg, val, true); - } else if (!TrySetValue_TwoOp(reg,val)) { +#ifdef HAVE_ARMV7 + // Use MOVW+MOVT for ARMv7+ + MOVW(reg, val & 0xFFFF); + if(val & 0xFFFF0000) + MOVT(reg, val, true); +#else + if (!TrySetValue_TwoOp(reg,val)) { + bool first = true; + for (int i = 0; i < 32; i += 2) { + u8 bits = RotR(val, i) & 0xFF; + if ((bits & 3) != 0) { + u8 rotation = i == 0 ? 0 : 16 - i / 2; + if (first) { + MOV(reg, Operand2(bits, rotation)); + first = false; + } else { + ORR(reg, reg, Operand2(bits, rotation)); + } + // Well, we took care of these other bits while we were at it. + i += 8 - 2; + } + } // Use literal pool for ARMv6. - AddNewLit(val); - LDR(reg, _PC); // To be backpatched later + // Disabled for now as it is crashing since Vertex Decoder JIT +// AddNewLit(val); +// LDR(reg, _PC); // To be backpatched later } +#endif } } @@ -702,12 +751,24 @@ void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedData void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);} void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);} void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);} -void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, false, dest, src, op2);} -void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, true, dest, src, op2);} +void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "LSR must have a non-zero shift (use LSL.)"); + WriteShiftedDataOp(2, false, dest, src, op2); +} +void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "LSRS must have a non-zero shift (use LSLS.)"); + WriteShiftedDataOp(2, true, dest, src, op2); +} void ARMXEmitter::LSR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, false, dest, src, op2);} void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, true, dest, src, op2);} -void ARMXEmitter::ASR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, false, dest, src, op2);} -void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, true, dest, src, op2);} +void ARMXEmitter::ASR (ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "ASR must have a non-zero shift (use LSL.)"); + WriteShiftedDataOp(4, false, dest, src, op2); +} +void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "ASRS must have a non-zero shift (use LSLS.)"); + WriteShiftedDataOp(4, true, dest, src, op2); +} void ARMXEmitter::ASR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, false, dest, src, op2);} void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, true, dest, src, op2);} @@ -754,6 +815,17 @@ void ARMXEmitter::CLZ(ARMReg rd, ARMReg rm) Write32(condition | (0x16F << 16) | (rd << 12) | (0xF1 << 4) | rm); } +void ARMXEmitter::PLD(ARMReg rn, int offset, bool forWrite) { + _dbg_assert_msg_(JIT, offset < 0x3ff && offset > -0x3ff, "PLD: Max 12 bits of offset allowed"); + + bool U = offset >= 0; + if (offset < 0) offset = -offset; + bool R = !forWrite; + // Conditions not allowed + Write32((0xF5 << 24) | (U << 23) | (R << 22) | (1 << 20) | ((int)rn << 16) | (0xF << 12) | offset); +} + + void ARMXEmitter::BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width) { u32 msb = (lsb + width - 1); @@ -998,21 +1070,6 @@ void ARMXEmitter::LDMBitmask(ARMReg dest, bool Add, bool Before, bool WriteBack, #undef VA_TO_REGLIST -ARMReg ARMXEmitter::SubBase(ARMReg Reg) -{ - if (Reg >= S0) - { - if (Reg >= D0) - { - if (Reg >= Q0) - return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register - return (ARMReg)(Reg - D0); - } - return (ARMReg)(Reg - S0); - } - return Reg; -} - // NEON Specific void ARMXEmitter::VABD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { @@ -1061,15 +1118,14 @@ void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | ((Vm & 0x10) << 2) | (Vm & 0xF)); } -// Double/single, Neon extern const VFPEnc VFPOps[16][2] = { - {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA + {{0xE0, 0xA0}, { -1, -1}}, // 0: VMLA {{0xE1, 0xA4}, { -1, -1}}, // 1: VNMLA - {{0xE0, 0xA4}, {0x22, 0xD1}}, // 2: VMLS + {{0xE0, 0xA4}, { -1, -1}}, // 2: VMLS {{0xE1, 0xA0}, { -1, -1}}, // 3: VNMLS - {{0xE3, 0xA0}, {0x20, 0xD0}}, // 4: VADD - {{0xE3, 0xA4}, {0x22, 0xD0}}, // 5: VSUB - {{0xE2, 0xA0}, {0x30, 0xD1}}, // 6: VMUL + {{0xE3, 0xA0}, { -1, -1}}, // 4: VADD + {{0xE3, 0xA4}, { -1, -1}}, // 5: VSUB + {{0xE2, 0xA0}, { -1, -1}}, // 6: VMUL {{0xE2, 0xA4}, { -1, -1}}, // 7: VNMUL {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 8: VABS(Vn(0x0) used for encoding) {{0xE8, 0xA0}, { -1, -1}}, // 9: VDIV @@ -1098,7 +1154,7 @@ const char *VFPOpNames[16] = { "VABSi", }; -u32 ARMXEmitter::EncodeVd(ARMReg Vd) +u32 EncodeVd(ARMReg Vd) { bool quad_reg = Vd >= Q0; bool double_reg = Vd >= D0; @@ -1107,27 +1163,29 @@ u32 ARMXEmitter::EncodeVd(ARMReg Vd) if (quad_reg) return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12); - else + else { if (double_reg) return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12); else return ((Reg & 0x1) << 22) | ((Reg & 0x1E) << 11); + } } -u32 ARMXEmitter::EncodeVn(ARMReg Vn) +u32 EncodeVn(ARMReg Vn) { bool quad_reg = Vn >= Q0; bool double_reg = Vn >= D0; - + ARMReg Reg = SubBase(Vn); if (quad_reg) return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3); - else + else { if (double_reg) return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3); else return ((Reg & 0x1E) << 15) | ((Reg & 0x1) << 7); + } } -u32 ARMXEmitter::EncodeVm(ARMReg Vm) +u32 EncodeVm(ARMReg Vm) { bool quad_reg = Vm >= Q0; bool double_reg = Vm >= D0; @@ -1135,12 +1193,62 @@ u32 ARMXEmitter::EncodeVm(ARMReg Vm) ARMReg Reg = SubBase(Vm); if (quad_reg) - return ((Reg & 0x10) << 2) | (Reg & 0xF); - else + return ((Reg & 0x10) << 1) | (Reg & 0xF); + else { if (double_reg) - return ((Reg & 0x10) << 2) | (Reg & 0xF); + return ((Reg & 0x10) << 1) | (Reg & 0xF); else return ((Reg & 0x1) << 5) | (Reg >> 1); + } +} + +u32 encodedSize(u32 value) +{ + if (value & I_8) + return 0; + else if (value & I_16) + return 1; + else if ((value & I_32) || (value & F_32)) + return 2; + else if (value & I_64) + return 3; + else + _dbg_assert_msg_(JIT, false, "Passed invalid size to integer NEON instruction"); + return 0; +} + +ARMReg SubBase(ARMReg Reg) +{ + if (Reg >= S0) + { + if (Reg >= D0) + { + if (Reg >= Q0) + return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register + return (ARMReg)(Reg - D0); + } + return (ARMReg)(Reg - S0); + } + return Reg; +} + +ARMReg DScalar(ARMReg dreg, int subScalar) { + int dr = (int)(SubBase(dreg)) & 0xF; + int scalar = ((subScalar << 4) | dr); + ARMReg ret = (ARMReg)(D0 + scalar); + // ILOG("Scalar: %i D0: %i AR: %i", scalar, (int)D0, (int)ret); + return ret; +} + +// Convert to a DScalar +ARMReg QScalar(ARMReg qreg, int subScalar) { + int dr = (int)(SubBase(qreg)) & 0xF; + if (subScalar & 2) { + dr++; + } + int scalar = (((subScalar & 1) << 4) | dr); + ARMReg ret = (ARMReg)(D0 + scalar); + return ret; } void ARMXEmitter::WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm) @@ -1386,6 +1494,1068 @@ void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags) } } +void ARMXEmitter::VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | EncodeVn(Vn) \ + | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x71 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | EncodeVn(Vn) \ + | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x50 << 4) | EncodeVm(Vm)); +} + +void ARMXEmitter::VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD << 8) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | EncodeVn(Vn) \ + | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | EncodeVn(Vn) \ + | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | EncodeVm(Vm)); +} + +void ARMXEmitter::VABS(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB1 << 16) | (encodedSize(Size) << 18) | EncodeVd(Vd) \ + | ((Size & F_32 ? 1 : 0) << 10) | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + // Only Float + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + // Only Float + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + VACGE(Vd, Vm, Vn); +} + +void ARMXEmitter::VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + VACGT(Vd, Vn, Vm); +} + +void ARMXEmitter::VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0x8 << 8) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \ + | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); +} + +void ARMXEmitter::VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \ + | EncodeVd(Vd) | EncodeVm(Vm)); +} +void ARMXEmitter::VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \ + | EncodeVd(Vd) | (1 << 8) | EncodeVm(Vm)); +} +void ARMXEmitter::VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + // _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + // _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + // _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (3 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + // _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + // _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + if (Size & F_32) + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); + +} +void ARMXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ + | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0x31 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ + | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x8 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + if (Size & F_32) + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xE0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ + | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ + | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + VCGE(Size, Vd, Vm, Vn); +} +void ARMXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ + | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (3 << 7) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCLS(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ + | EncodeVd(Vd) | (1 << 10) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + VCGT(Size, Vd, Vm, Vn); +} +void ARMXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ + | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x20 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCLZ(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ + | EncodeVd(Vd) | (0x48 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VCNT(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, Size & I_8, "Can only use I_8 with " __FUNCTION__); + + bool register_quad = Vd >= Q0; + Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ + | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + u32 imm4 = 0; + if (Size & I_8) + imm4 = (index << 1) | 1; + else if (Size & I_16) + imm4 = (index << 2) | 2; + else if (Size & (I_32 | F_32)) + imm4 = (index << 3) | 4; + Write32((0xF3 << 24) | (0xB << 20) | (imm4 << 16) \ + | EncodeVd(Vd) | (0xC << 8) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Rt) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Rt < D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Vd = SubBase(Vd); + u8 sizeEncoded = 0; + if (Size & I_8) + sizeEncoded = 2; + else if (Size & I_16) + sizeEncoded = 1; + else if (Size & I_32) + sizeEncoded = 0; + + Write32((0xEE << 24) | (0x8 << 20) | ((sizeEncoded & 2) << 21) | (register_quad << 21) \ + | ((Vd & 0xF) << 16) | (Rt << 12) | (0xD1 << 4) | ((Vd & 0x10) << 3) | (1 << 4)); +} +void ARMXEmitter::VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (0xB << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (index & 0xF) \ + | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, cpu_info.bVFPv4, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, cpu_info.bVFPv4, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (1 << 9) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (0x60 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (0x61 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (1 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vn >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm < Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float."); + + Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ + | EncodeVn(Vn) | EncodeVd(Vd) | (0xA0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_POLYNOMIAL) ? (1 << 24) : 0) | (encodedSize(Size) << 20) | \ + EncodeVn(Vn) | EncodeVd(Vd) | (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xC0 << 4) | ((Size & I_POLYNOMIAL) ? 1 << 9 : 0) | EncodeVm(Vm)); +} +void ARMXEmitter::VMLA_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + // No idea if the Non-Q case here works. Not really that interested. + if (Size & F_32) + Write32((0xF2 << 24) | (register_quad << 24) | (1 << 23) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x14 << 4) | EncodeVm(Vm)); + else + _dbg_assert_msg_(JIT, false, "VMLA_scalar only supports float atm"); + //else + // Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (1 << 6) | EncodeVm(Vm)); + // Unsigned support missing +} +void ARMXEmitter::VMUL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + int VmEnc = EncodeVm(Vm); + // No idea if the Non-Q case here works. Not really that interested. + if (Size & F_32) // Q flag + Write32((0xF2 << 24) | (register_quad << 24) | (1 << 23) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x94 << 4) | VmEnc); + else + _dbg_assert_msg_(JIT, false, "VMUL_scalar only supports float atm"); + + // Write32((0xF2 << 24) | ((Size & I_POLYNOMIAL) ? (1 << 24) : 0) | (1 << 23) | (encodedSize(Size) << 20) | + // EncodeVn(Vn) | EncodeVd(Vd) | (0x84 << 4) | (register_quad << 6) | EncodeVm(Vm)); + // Unsigned support missing +} + +void ARMXEmitter::VNEG(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) | \ + EncodeVd(Vd) | ((Size & F_32) ? 1 << 10 : 0) | (0xE << 6) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (3 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VPADAL(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x60 << 4) | ((Size & I_UNSIGNED) ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB1 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VPADDL(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x20 << 4) | (Size & I_UNSIGNED ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA1 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQABS(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x90 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQNEG(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x78 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x51 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x41 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x21 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VRECPE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (0xB << 16) | EncodeVd(Vd) | \ + (0x40 << 4) | (Size & F_32 ? 1 << 8 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x50 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + Write32((0xF3 << 24) | (0xB << 20) | ((Vd & 0x10) << 18) | (0xB << 16) + | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) + | ((Vm & 0x10) << 1) | (Vm & 0xF)); +} +void ARMXEmitter::VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x80 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x20 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x30 << 4) | EncodeVm(Vm)); +} +void ARMXEmitter::VSWP(ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (1 << 17) | EncodeVd(Vd) | \ + (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VTRN(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (1 << 7) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VUZP(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void ARMXEmitter::VZIP(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x18 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} + +void ARMXEmitter::VMOVL(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vm >= D0 && Vm <= D31, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(JIT, (Size & (I_UNSIGNED | I_SIGNED)) != 0, "Must specify I_SIGNED or I_UNSIGNED in VMOVL"); + + bool unsign = (Size & I_UNSIGNED) != 0; + int imm3 = 0; + if (Size & I_8) imm3 = 1; + if (Size & I_16) imm3 = 2; + if (Size & I_32) imm3 = 4; + + Write32((0xF2 << 24) | (unsign << 24) | (1 << 23) | (imm3 << 19) | EncodeVd(Vd) | \ + (0xA1 << 4) | EncodeVm(Vm)); +} + +void ARMXEmitter::VMOVN(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, Vm >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, Vd >= D0 && Vd <= D31, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(JIT, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3B << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | (1 << 9) | EncodeVm(Vm)); +} + +void ARMXEmitter::VCVT(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(JIT, (Size & (I_UNSIGNED | I_SIGNED)) != 0, "Must specify I_SIGNED or I_UNSIGNED in VCVT NEON"); + + bool register_quad = Vd >= Q0; + bool toInteger = (Size & I_32) != 0; + bool isUnsigned = (Size & I_UNSIGNED) != 0; + int op = (toInteger << 1) | (int)isUnsigned; + + Write32((0xF3 << 24) | (0xBB << 16) | EncodeVd(Vd) | (0x3 << 9) | (op << 7) | (register_quad << 6) | EncodeVm(Vm)); +} + +static int RegCountToType(int nRegs, NEONAlignment align) { + switch (nRegs) { + case 1: + _dbg_assert_msg_(JIT, !((int)align & 1), "align & 1 must be == 0"); + return 7; + case 2: + _dbg_assert_msg_(JIT, !((int)align & 3), "align & 3 must be == 0"); + return 10; + case 3: + _dbg_assert_msg_(JIT, !((int)align & 1), "align & 1 must be == 0"); + return 6; + case 4: + return 4; + default: + _dbg_assert_msg_(JIT, false, "Invalid number of registers passed to vector load/store"); + return 0; + } +} + +void ARMXEmitter::WriteVLDST1(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm) +{ + u32 spacing = RegCountToType(regCount, align); // Only support loading to 1 reg + // Gets encoded as a double register + Vd = SubBase(Vd); + + Write32((0xF4 << 24) | ((Vd & 0x10) << 18) | (load << 21) | (Rn << 16) + | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) + | (align << 4) | Rm); +} + +void ARMXEmitter::VLD1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm) { + WriteVLDST1(true, Size, Vd, Rn, regCount, align, Rm); +} + +void ARMXEmitter::VST1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm) { + WriteVLDST1(false, Size, Vd, Rn, regCount, align, Rm); +} + +void ARMXEmitter::WriteVLDST1_lane(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm) +{ + bool register_quad = Vd >= Q0; + + Vd = SubBase(Vd); + // Support quad lanes by converting to D lanes + if (register_quad && lane > 1) { + Vd = (ARMReg)((int)Vd + 1); + lane -= 2; + } + int encSize = encodedSize(Size); + int index_align = 0; + switch (encSize) { + case 0: index_align = lane << 1; break; + case 1: index_align = lane << 2; if (aligned) index_align |= 1; break; + case 2: index_align = lane << 3; if (aligned) index_align |= 3; break; + default: + break; + } + + Write32((0xF4 << 24) | (1 << 23) | ((Vd & 0x10) << 18) | (load << 21) | (Rn << 16) + | ((Vd & 0xF) << 12) | (encSize << 10) + | (index_align << 4) | Rm); +} + +void ARMXEmitter::VLD1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm) { + WriteVLDST1_lane(true, Size, Vd, Rn, lane, aligned, Rm); +} + +void ARMXEmitter::VST1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm) { + WriteVLDST1_lane(false, Size, Vd, Rn, lane, aligned, Rm); +} + +void ARMXEmitter::VLD1_all_lanes(u32 Size, ARMReg Vd, ARMReg Rn, bool aligned, ARMReg Rm) { + bool register_quad = Vd >= Q0; + + Vd = SubBase(Vd); + + int T = register_quad; // two D registers + + Write32((0xF4 << 24) | (1 << 23) | ((Vd & 0x10) << 18) | (1 << 21) | (Rn << 16) + | ((Vd & 0xF) << 12) | (0xC << 8) | (encodedSize(Size) << 6) + | (T << 5) | (aligned << 4) | Rm); +} + +/* +void ARMXEmitter::VLD2(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm) +{ + u32 spacing = 0x8; // Single spaced registers + // Gets encoded as a double register + Vd = SubBase(Vd); + + Write32((0xF4 << 24) | ((Vd & 0x10) << 18) | (1 << 21) | (Rn << 16) + | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) + | (align << 4) | Rm); +} +*/ + +void ARMXEmitter::VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm) +{ + bool register_quad = Vd >= Q0; + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + Write32((0xF3 << 24) | (1 << 23) | ((Vd & 0x10) << 18) | (0x3 << 20) + | (encodedSize(Size) << 18) | ((Vd & 0xF) << 12) | (size << 7) + | (register_quad << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF)); +} + +void ARMXEmitter::VREV64(u32 Size, ARMReg Vd, ARMReg Vm) +{ + VREVX(0, Size, Vd, Vm); +} + +void ARMXEmitter::VREV32(u32 Size, ARMReg Vd, ARMReg Vm) +{ + VREVX(1, Size, Vd, Vm); +} + +void ARMXEmitter::VREV16(u32 Size, ARMReg Vd, ARMReg Vm) +{ + VREVX(2, Size, Vd, Vm); +} + // UNTESTED // See page A8-878 in ARMv7-A Architecture Reference Manual diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index 868c5bcdb3..117b5ef28b 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -70,6 +70,9 @@ enum ARMReg // ASIMD Quad-Word registers Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, + + // for NEON VLD/VST instructions + REG_UPDATE = R13, INVALID_REG = 0xFFFFFFFF }; @@ -346,9 +349,44 @@ struct LiteralPool typedef const u8* JumpTarget; +// XXX: Stop polluting the global namespace +const u32 I_8 = (1 << 0); +const u32 I_16 = (1 << 1); +const u32 I_32 = (1 << 2); +const u32 I_64 = (1 << 3); +const u32 I_SIGNED = (1 << 4); +const u32 I_UNSIGNED = (1 << 5); +const u32 F_32 = (1 << 6); +const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL + +u32 EncodeVd(ARMReg Vd); +u32 EncodeVn(ARMReg Vn); +u32 EncodeVm(ARMReg Vm); + +u32 encodedSize(u32 value); + +// Subtracts the base from the register to give us the real one +ARMReg SubBase(ARMReg Reg); + +// See A.7.1 in the ARMv7-A +// VMUL F32 scalars can only be up to D15[0], D15[1] - higher scalars cannot be individually addressed +ARMReg DScalar(ARMReg dreg, int subScalar); +ARMReg QScalar(ARMReg qreg, int subScalar); + +enum NEONAlignment { + ALIGN_NONE = 0, + ALIGN_64 = 1, + ALIGN_128 = 2, + ALIGN_256 = 3 +}; + + +class NEONXEmitter; + class ARMXEmitter { friend struct OpArg; // for Write8 etc + friend class NEONXEmitter; private: u8 *code, *startcode; u8 *lastCacheFlushEnd; @@ -361,9 +399,6 @@ private: void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2); void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2); - u32 EncodeVd(ARMReg Vd); - u32 EncodeVn(ARMReg Vn); - u32 EncodeVm(ARMReg Vm); void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm); void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); @@ -371,6 +406,9 @@ private: // New Ops void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false); + void WriteVLDST1(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm); + void WriteVLDST1_lane(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm); + protected: inline void Write32(u32 value) {*(u32*)code = value; code+=4;} @@ -449,7 +487,6 @@ public: void ADDS(ARMReg dest, ARMReg src, Operand2 op2); void ADC (ARMReg dest, ARMReg src, Operand2 op2); void ADCS(ARMReg dest, ARMReg src, Operand2 op2); - void LSL (ARMReg dest, ARMReg src, Operand2 op2); void LSL (ARMReg dest, ARMReg src, ARMReg op2); void LSLS(ARMReg dest, ARMReg src, Operand2 op2); @@ -505,6 +542,7 @@ public: void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width); void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width); void CLZ(ARMReg rd, ARMReg rm); + void PLD(ARMReg rd, int offset, bool forWrite = false); // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...) // Just need to put an underscore here, bit annoying. @@ -543,12 +581,10 @@ public: // is deprecating conditional execution of ASIMD instructions. // ASIMD instructions don't even have a conditional encoding. - // Subtracts the base from the register to give us the real one - ARMReg SubBase(ARMReg Reg); // NEON Only - void VABD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABD(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADD(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm); // VFP Only void VLDR(ARMReg Dest, ARMReg Base, s16 offset); @@ -582,6 +618,163 @@ public: void VCVTF32F16(ARMReg Dest, ARMReg Src); void VCVTF16F32(ARMReg Dest, ARMReg Src); + void VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABS(u32 Size, ARMReg Vd, ARMReg Vm); + void VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLS(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLZ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCNT(u32 Size, ARMReg Vd, ARMReg Vm); + void VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index); + void VDUP(u32 Size, ARMReg Vd, ARMReg Rt); + void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index); + void VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + + // Three registers + void VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + + // Two registers and a scalar + // These two are super useful for matrix multiplication + void VMUL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLA_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + + // TODO: + /* + void VMLS_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLAL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLSL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMULL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLAL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLSL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULH_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQRDMULH_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + */ + + void VNEG(u32 Size, ARMReg Vd, ARMReg Vm); + void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADAL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADDL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQABS(u32 Size, ARMReg Vd, ARMReg Vm); + void VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQNEG(u32 Size, ARMReg Vd, ARMReg Vm); + void VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRECPE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSWP(ARMReg Vd, ARMReg Vm); + void VTRN(u32 Size, ARMReg Vd, ARMReg Vm); + void VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VUZP(u32 Size, ARMReg Vd, ARMReg Vm); + void VZIP(u32 Size, ARMReg Vd, ARMReg Vm); + void VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm); + void VREV64(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV32(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV16(u32 Size, ARMReg Vd, ARMReg Vm); + + + // Widening and narrowing moves + void VMOVL(u32 Size, ARMReg Vd, ARMReg Vm); + void VMOVN(u32 Size, ARMReg Vd, ARMReg Vm); + + // Vector VCVT + void VCVT(u32 DestSize, ARMReg Dest, ARMReg Src); + + + // Notes: + // Rm == _PC is interpreted as no offset, otherwise, effective address is sum of Rn and Rm + // Rm == R13 is interpreted as VLD1, .... [Rn]! Added a REG_UPDATE pseudo register. + + // Load/store multiple registers full of elements (a register is a D register) + // Specifying alignment when it can be guaranteed is documented to improve load/store performance. + // For example, when loading a set of four 64-bit registers that we know is 32-byte aligned, we should specify ALIGN_256. + void VLD1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + + // Load/store single lanes of D registers + void VLD1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm = _PC); + void VST1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm = _PC); + + // Load one value into all lanes of a D or a Q register (either supported, all formats should work). + void VLD1_all_lanes(u32 Size, ARMReg Vd, ARMReg Rn, bool aligned, ARMReg Rm = _PC); + + /* + // Deinterleave two loads... or something. TODO + void VLD2(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST2(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + + void VLD2_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + void VST2_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + + void VLD3(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST3(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + + void VLD3_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + void VST3_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + + void VLD4(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST4(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + + void VLD4_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + void VST4_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC); + */ + void VMRS_APSR(); void VMRS(ARMReg Rt); void VMSR(ARMReg Rt); @@ -592,13 +785,16 @@ public: void MOVI2R(ARMReg reg, u32 val, bool optimize = true); void MOVI2F(ARMReg dest, float val, ARMReg tempReg, bool negate = false); + // Load pointers without casting + template void MOVP2R(ARMReg reg, T *val) { + MOVI2R(reg, (u32)(intptr_t)(void *)val); + } + void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch); void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch); void CMPI2R(ARMReg rs, u32 val, ARMReg scratch); void TSTI2R(ARMReg rs, u32 val, ARMReg scratch); void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch); - - }; // class ARMXEmitter @@ -635,14 +831,16 @@ public: // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. void FreeCodeSpace() { -#ifndef __SYMBIAN32__ +#ifdef __SYMBIAN32__ + ResetExecutableMemory(region); +#else FreeMemoryPages(region, region_size); #endif region = NULL; region_size = 0; } - bool IsInSpace(u8 *ptr) + bool IsInSpace(const u8 *ptr) const { return ptr >= region && ptr < region + region_size; } @@ -672,7 +870,7 @@ public: return region; } - size_t GetOffset(u8 *ptr) { + size_t GetOffset(const u8 *ptr) const { return ptr - region; } }; diff --git a/Common/Atomic_GCC.h b/Common/Atomic_GCC.h index 2ee4622da1..5024b759bc 100644 --- a/Common/Atomic_GCC.h +++ b/Common/Atomic_GCC.h @@ -21,7 +21,7 @@ #ifdef BLACKBERRY #include #elif defined(__SYMBIAN32__) -#include +#include #endif #include "Common.h" @@ -63,12 +63,16 @@ inline u32 AtomicLoad(volatile u32& src) { return src; // 32-bit reads are always atomic. } inline u32 AtomicLoadAcquire(volatile u32& src) { +#ifdef __SYMBIAN32__ + return __e32_atomic_load_acq32(&src); +#else //keep the compiler from caching any memory references u32 result = src; // 32-bit reads are always atomic. //__sync_synchronize(); // TODO: May not be necessary. // Compiler instruction only. x86 loads always have acquire semantics. __asm__ __volatile__ ( "":::"memory" ); return result; +#endif } inline void AtomicOr(volatile u32& target, u32 value) { @@ -82,57 +86,12 @@ inline void AtomicStoreRelease(volatile u32& dest, u32 value) { #ifdef BLACKBERRY atomic_set(&dest, value); #elif defined(__SYMBIAN32__) - g_atomic_int_set(&dest, value); + __e32_atomic_store_rel32(&dest, value); #else - __sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics. + __sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function has acquire semantics. #endif } } -// Old code kept here for reference in case we need the parts with __asm__ __volatile__. -#if 0 -LONG SyncInterlockedIncrement(LONG *Dest) -{ -#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) - return __sync_add_and_fetch(Dest, 1); -#else - register int result; - __asm__ __volatile__("lock; xadd %0,%1" - : "=r" (result), "=m" (*Dest) - : "0" (1), "m" (*Dest) - : "memory"); - return result; -#endif -} - -LONG SyncInterlockedExchangeAdd(LONG *Dest, LONG Val) -{ -#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) - return __sync_add_and_fetch(Dest, Val); -#else - register int result; - __asm__ __volatile__("lock; xadd %0,%1" - : "=r" (result), "=m" (*Dest) - : "0" (Val), "m" (*Dest) - : "memory"); - return result; -#endif -} - -LONG SyncInterlockedExchange(LONG *Dest, LONG Val) -{ -#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) - return __sync_lock_test_and_set(Dest, Val); -#else - register int result; - __asm__ __volatile__("lock; xchg %0,%1" - : "=r" (result), "=m" (*Dest) - : "0" (Val), "m" (*Dest) - : "memory"); - return result; -#endif -} -#endif - #endif diff --git a/Common/CPUDetect.cpp b/Common/CPUDetect.cpp index 19e557f9ea..a7aa7fc09e 100644 --- a/Common/CPUDetect.cpp +++ b/Common/CPUDetect.cpp @@ -36,7 +36,7 @@ #undef _interlockedbittestandreset64 #else -#if !defined(_M_GENERIC) && !defined(MIPS) +#ifdef _M_SSE #include #endif @@ -45,8 +45,7 @@ #include #elif !defined(MIPS) -void __cpuidex(int regs[4], int cpuid_leaf, int ecxval) -{ +void __cpuidex(int regs[4], int cpuid_leaf, int ecxval) { #ifdef ANDROID // Use the /dev/cpu/%i/cpuid interface int f = open("/dev/cpu/0/cpuid", O_RDONLY); @@ -90,8 +89,7 @@ CPUInfo::CPUInfo() { } // Detects the various cpu features -void CPUInfo::Detect() -{ +void CPUInfo::Detect() { memset(this, 0, sizeof(*this)); #ifdef _M_IX86 Mode64bit = false; @@ -154,7 +152,11 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 9) & 1) bSSSE3 = true; if ((cpu_id[2] >> 19) & 1) bSSE4_1 = true; if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; - if ((cpu_id[2] >> 28) & 1) bAVX = true; + if ((cpu_id[2] >> 28) & 1) { + bAVX = true; + if ((cpu_id[2] >> 12) & 1) + bFMA = true; + } if ((cpu_id[2] >> 25) & 1) bAES = true; } if (max_ex_fn >= 0x80000004) { @@ -231,6 +233,7 @@ std::string CPUInfo::Summarize() if (bSSE4_2) sum += ", SSE4.2"; if (HTT) sum += ", HTT"; if (bAVX) sum += ", AVX"; + if (bAVX) sum += ", FMA"; if (bAES) sum += ", AES"; if (bLongMode) sum += ", 64-bit support"; return sum; diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index 4ca4712bb6..04c615b412 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -19,26 +19,29 @@ #ifndef _CPUDETECT_H_ #define _CPUDETECT_H_ +// Every architecture has its own define. This needs to be added to. +#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) +#define HAVE_ARMV7 1 +#endif + #include -enum CPUVendor -{ +enum CPUVendor { VENDOR_INTEL = 0, VENDOR_AMD = 1, VENDOR_ARM = 2, VENDOR_OTHER = 3, }; -struct CPUInfo -{ +struct CPUInfo { CPUVendor vendor; - + char cpu_string[0x21]; char brand_string[0x41]; bool OS64bit; bool CPU64bit; bool Mode64bit; - + bool HTT; int num_cores; int logical_cpu_count; @@ -53,10 +56,11 @@ struct CPUInfo bool bLZCNT; bool bSSE4A; bool bAVX; + bool bFMA; bool bAES; bool bLAHFSAHF64; bool bLongMode; - + // ARM specific CPUInfo bool bSwp; bool bHalf; @@ -71,7 +75,6 @@ struct CPUInfo bool bVFPv4; bool bIDIVa; bool bIDIVt; - bool bArmV7; // enable MOVT, MOVW etc // ARMv8 specific bool bFP; @@ -79,7 +82,7 @@ struct CPUInfo // Call Detect() explicit CPUInfo(); - + // Turn the cpu info into a string we can show std::string Summarize(); diff --git a/Common/Common.h b/Common/Common.h index df4b22acba..8604128025 100644 --- a/Common/Common.h +++ b/Common/Common.h @@ -146,6 +146,8 @@ private: # define _M_SSE 0x301 # elif defined __SSE3__ # define _M_SSE 0x300 +# elif defined __SSE2__ +# define _M_SSE 0x200 # endif #elif ((_MSC_VER >= 1500) || __INTEL_COMPILER) // Visual Studio 2008 # define _M_SSE 0x402 diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 447c5861ec..be412443ea 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -183,16 +183,13 @@ - - - @@ -216,7 +213,6 @@ - @@ -228,7 +224,6 @@ Create - diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 62a187b5f0..c91b201d5a 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -16,14 +16,11 @@ - - - @@ -47,13 +44,11 @@ - - diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index 24f151ba92..2ae97a644a 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -37,7 +37,10 @@ #include #include #include -#endif +#if !defined(IOS) +#include +#endif // !defined(IOS) +#endif // __APPLE__ #include "util/text/utf8.h" @@ -254,11 +257,11 @@ bool CreateDir(const std::string &path) bool CreateFullPath(const std::string &fullPath) { int panicCounter = 100; - INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); + DEBUG_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); if (File::Exists(fullPath)) { - INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str()); + DEBUG_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str()); return true; } @@ -641,21 +644,50 @@ bool SetCurrentDir(const std::string &directory) return __chdir(directory.c_str()) == 0; } -#ifdef _WIN32 -std::wstring &GetExeDirectory() +const std::string &GetExeDirectory() { - static std::wstring DolphinPath; - if (DolphinPath.empty()) + static std::string ExePath; + + if (ExePath.empty()) { - wchar_t Dolphin_exe_Path[2048]; - GetModuleFileName(NULL, Dolphin_exe_Path, 2048); - DolphinPath = Dolphin_exe_Path; - DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); - } - return DolphinPath; -} +#ifdef _WIN32 + TCHAR program_path[4096] = {0}; + GetModuleFileName(NULL, program_path, ARRAY_SIZE(program_path) - 1); + program_path[ARRAY_SIZE(program_path) - 1] = '\0'; + TCHAR *last_slash = _tcsrchr(program_path, '\\'); + if (last_slash != NULL) + *(last_slash + 1) = '\0'; +#ifdef UNICODE + ExePath = ConvertWStringToUTF8(program_path); +#else + ExePath = program_path; #endif +#elif (defined(__APPLE__) && !defined(IOS)) || defined(__linux__) + char program_path[4096]; + uint32_t program_path_size = sizeof(program_path) - 1; + +#if defined(__linux__) + if (readlink("/proc/self/exe", program_path, 4095) > 0) +#elif defined(__APPLE__) && !defined(IOS) + if (_NSGetExecutablePath(program_path, &program_path_size) == 0) +#else +#error Unmatched ifdef. +#endif + { + program_path[sizeof(program_path) - 1] = '\0'; + char *last_slash = strrchr(program_path, '/'); + if (last_slash != NULL) + *(last_slash + 1) = '\0'; + ExePath = program_path; + } +#endif + } + + return ExePath; +} + + IOFile::IOFile() : m_file(NULL), m_good(true) {} diff --git a/Common/FileUtil.h b/Common/FileUtil.h index 79f46f7188..a7727eed40 100644 --- a/Common/FileUtil.h +++ b/Common/FileUtil.h @@ -102,9 +102,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path); // Set the current directory to given directory bool SetCurrentDir(const std::string &directory); -#ifdef _WIN32 -std::wstring &GetExeDirectory(); -#endif +const std::string &GetExeDirectory(); // simple wrapper for cstdlib file functions to // hopefully will make error checking easier diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index 4f94900a83..9be86d1072 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -67,6 +67,7 @@ static const DefMappingStruct defaultQwertyKeyboardKeyMap[] = { {VIRTKEY_UNTHROTTLE , NKCODE_TAB}, {VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE}, {VIRTKEY_PAUSE , NKCODE_ESCAPE}, + {VIRTKEY_REWIND , NKCODE_DEL}, }; static const DefMappingStruct defaultAzertyKeyboardKeyMap[] = { @@ -95,6 +96,7 @@ static const DefMappingStruct defaultAzertyKeyboardKeyMap[] = { {VIRTKEY_UNTHROTTLE , NKCODE_TAB}, {VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE}, {VIRTKEY_PAUSE , NKCODE_ESCAPE}, + {VIRTKEY_REWIND , NKCODE_DEL}, }; static const DefMappingStruct defaultQwertzKeyboardKeyMap[] = { @@ -123,6 +125,7 @@ static const DefMappingStruct defaultQwertzKeyboardKeyMap[] = { {VIRTKEY_UNTHROTTLE , NKCODE_TAB}, {VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE}, {VIRTKEY_PAUSE , NKCODE_ESCAPE}, + {VIRTKEY_REWIND , NKCODE_DEL}, }; static const DefMappingStruct default360KeyMap[] = { @@ -190,6 +193,7 @@ static const DefMappingStruct defaultBlackberryQWERTYKeyMap[] = { {VIRTKEY_UNTHROTTLE , NKCODE_TAB}, {VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE}, {VIRTKEY_PAUSE , NKCODE_ESCAPE}, + {VIRTKEY_REWIND , NKCODE_DEL}, }; static const DefMappingStruct defaultPadMap[] = { @@ -279,17 +283,17 @@ void UpdateConfirmCancelKeys() { int confirmKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE; int cancelKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS; - for(auto i = g_controllerMap[confirmKey].begin(); i != g_controllerMap[confirmKey].end(); ++i) { + for (auto i = g_controllerMap[confirmKey].begin(); i != g_controllerMap[confirmKey].end(); ++i) { confirmKeys.push_back((keycode_t)i->keyCode); } - for(auto i = g_controllerMap[cancelKey].begin(); i != g_controllerMap[cancelKey].end(); ++i) { + for (auto i = g_controllerMap[cancelKey].begin(); i != g_controllerMap[cancelKey].end(); ++i) { cancelKeys.push_back((keycode_t)i->keyCode); } // Push several hard-coded keys before submitting to native. - const keycode_t hardcodedConfirmKeys[] = { - NKCODE_SPACE, + const keycode_t hardcodedConfirmKeys[] = { + NKCODE_SPACE, NKCODE_ENTER, }; @@ -299,9 +303,9 @@ void UpdateConfirmCancelKeys() { confirmKeys.push_back(hardcodedConfirmKeys[i]); } - const keycode_t hardcodedCancelKeys[] = { - NKCODE_ESCAPE, - NKCODE_BACK, + const keycode_t hardcodedCancelKeys[] = { + NKCODE_ESCAPE, + NKCODE_BACK, }; for (size_t i = 0; i < ARRAY_SIZE(hardcodedCancelKeys); i++) { @@ -329,7 +333,6 @@ void SetDefaultKeyMap(DefaultMaps dmap, bool replace) { bool qwertz = false; #ifdef _WIN32 HKL localeId = GetKeyboardLayout(0); - // TODO: Is this list complete enough? switch ((int)localeId & 0xFFFF) { case 0x407: @@ -360,7 +363,8 @@ void SetDefaultKeyMap(DefaultMaps dmap, bool replace) { SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace); break; case DEFAULT_MAPPING_BLACKBERRY_QWERTY: - SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultBlackberryQWERTYKeyMap, ARRAY_SIZE(defaultBlackberryQWERTYKeyMap), replace); + SetDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultBlackberryQWERTYKeyMap, ARRAY_SIZE(defaultBlackberryQWERTYKeyMap), replace); + replace = false; case DEFAULT_MAPPING_PAD: SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultPadMap, ARRAY_SIZE(defaultPadMap), replace); break; @@ -426,7 +430,7 @@ const KeyMap_IntStrPair key_names[] = { {NKCODE_F10, "F10"}, {NKCODE_F11, "F11"}, {NKCODE_F12, "F12"}, - + {NKCODE_GRAVE, "`"}, {NKCODE_SLASH, "/"}, {NKCODE_BACKSLASH, "\\"}, @@ -453,7 +457,8 @@ const KeyMap_IntStrPair key_names[] = { {NKCODE_ALT_RIGHT, "RAlt"}, {NKCODE_SPACE, "Space"}, {NKCODE_WINDOW, "Windows"}, - {NKCODE_DEL, "Del"}, + {NKCODE_DEL, "Backspace"}, + {NKCODE_FORWARD_DEL, "Delete"}, {NKCODE_MOVE_HOME, "Home"}, {NKCODE_MOVE_END, "End"}, {NKCODE_ESCAPE, "Esc"}, @@ -601,6 +606,11 @@ const KeyMap_IntStrPair psp_button_names[] = { {VIRTKEY_UNTHROTTLE, "Unthrottle"}, {VIRTKEY_SPEED_TOGGLE, "SpeedToggle"}, {VIRTKEY_PAUSE, "Pause"}, +#ifndef USING_GLES2 + {VIRTKEY_REWIND, "Rewind"}, +#endif + {VIRTKEY_SAVE_STATE, "Save State"}, + {VIRTKEY_LOAD_STATE, "Load State"}, {VIRTKEY_AXIS_RIGHT_Y_MAX, "RightAn.Up"}, {VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"}, @@ -671,27 +681,20 @@ KeyDef AxisDef(int deviceId, int axisId, int direction) { return KeyDef(deviceId, TranslateKeyCodeFromAxis(axisId, direction)); } -static bool FindKeyMapping(int deviceId, int key, int *psp_button) { +static bool FindKeyMapping(int deviceId, int key, std::vector *psp_button) { // Brute force, let's optimize later for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) { for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) { if (*iter2 == KeyDef(deviceId, key)) { - *psp_button = iter->first; - return true; + psp_button->push_back(iter->first); } } } - return false; + return psp_button->size() > 0; } -int KeyToPspButton(int deviceId, int key) { - int search_start_layer = 0; - int psp_button; - - if (FindKeyMapping(deviceId, key, &psp_button)) - return psp_button; - - return KEYMAP_ERROR_UNKNOWN_KEY; +bool KeyToPspButton(int deviceId, int key, std::vector *pspKeys) { + return FindKeyMapping(deviceId, key, pspKeys); } // TODO: vector output @@ -708,9 +711,9 @@ bool KeyFromPspButton(int btn, std::vector *keys) { return false; } -int AxisToPspButton(int deviceId, int axisId, int direction) { +bool AxisToPspButton(int deviceId, int axisId, int direction, std::vector *pspKeys) { int key = TranslateKeyCodeFromAxis(axisId, direction); - return KeyToPspButton(deviceId, key); + return KeyToPspButton(deviceId, key, pspKeys); } bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) { diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 604a861e2f..9d69ffedd9 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -40,6 +40,9 @@ enum { VIRTKEY_AXIS_RIGHT_Y_MIN = 0x10009, VIRTKEY_AXIS_RIGHT_X_MAX = 0x1000a, VIRTKEY_AXIS_RIGHT_Y_MAX = 0x1000b, + VIRTKEY_REWIND = 0x1000c, + VIRTKEY_SAVE_STATE = 0x1000d, + VIRTKEY_LOAD_STATE = 0x1000e, VIRTKEY_LAST, VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST }; @@ -95,9 +98,9 @@ typedef std::map> KeyMapping; // KeyMap // A translation layer for key assignment. Provides // integration with Core's config state. -// +// // Does not handle input state managment. -// +// // Platform ports should map their platform's keys to KeyMap's keys (NKCODE_*). // // Then have KeyMap transform those into psp buttons. @@ -113,7 +116,7 @@ namespace KeyMap { std::string name; }; - // Use if you need to display the textual name + // Use if you need to display the textual name std::string GetKeyName(int keyCode); std::string GetKeyOrAxisName(int keyCode); std::string GetAxisName(int axisId); @@ -124,10 +127,7 @@ namespace KeyMap { // Use if to translate KeyMap Keys to PSP // buttons. You should have already translated // your platform's keys to KeyMap keys. - // - // Returns KEYMAP_ERROR_UNKNOWN_KEY - // for any unmapped key - int KeyToPspButton(int deviceId, int key); + bool KeyToPspButton(int deviceId, int key, std::vector *pspKeys); bool KeyFromPspButton(int btn, std::vector *keys); int TranslateKeyCodeToAxis(int keyCode, int &direction); @@ -141,7 +141,7 @@ namespace KeyMap { // Direction is negative or positive. void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace); - int AxisToPspButton(int deviceId, int axisId, int direction); + bool AxisToPspButton(int deviceId, int axisId, int direction, std::vector *pspKeys); bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction); std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction); diff --git a/Common/LogManager.h b/Common/LogManager.h index 38ea882062..d7ded3de8e 100644 --- a/Common/LogManager.h +++ b/Common/LogManager.h @@ -19,11 +19,11 @@ #include "Log.h" #include "StringUtils.h" -#include "Thread.h" #include "FileUtil.h" #include "file/ini_file.h" #include +#include "StdMutex.h" #define MAX_MESSAGES 8000 #define MAX_MSGLEN 1024 diff --git a/Common/MathUtil.cpp b/Common/MathUtil.cpp deleted file mode 100644 index 1e4ef5aac3..0000000000 --- a/Common/MathUtil.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "MathUtil.h" - -int GetPow2(int x) -{ - int ret = 0; - int val = 1; - while(x > val) - { - ret++; - val *= 2; - } - return ret; -} - diff --git a/Common/MathUtil.h b/Common/MathUtil.h deleted file mode 100644 index 3ae49b39e1..0000000000 --- a/Common/MathUtil.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _MATH_UTIL_H_ -#define _MATH_UTIL_H_ - -int GetPow2(int x); - -#endif // _MATH_UTIL_H_ diff --git a/Common/MemArena.cpp b/Common/MemArena.cpp index 327c974c07..f228c6274a 100644 --- a/Common/MemArena.cpp +++ b/Common/MemArena.cpp @@ -175,6 +175,12 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) return ptr; #else void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | +// Do not sync memory to underlying file. Linux has this by default. +#ifdef BLACKBERRY + MAP_NOSYNCFILE | +#elif defined(__FreeBSD__) + MAP_NOSYNC | +#endif ((base == 0) ? 0 : MAP_FIXED), fd, offset); if (retval == MAP_FAILED) @@ -216,7 +222,6 @@ u8* MemArena::Find4GBBase() #else // 32 bit #ifdef _WIN32 - // The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it. u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE); if (base) { VirtualFree(base, 0, MEM_RELEASE); @@ -244,8 +249,6 @@ u8* MemArena::Find4GBBase() // if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) // continue; - - static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) { // OK, we know where to find free space. Now grab it! // We just mimic the popular BAT setup. @@ -265,6 +268,8 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 for (i = 0; i < num_views; i++) { const MemoryView &view = views[i]; + if (view.size == 0) + continue; SKIP(flags, view.flags); if (view.flags & MV_MIRROR_PREVIOUS) { position = last_position; @@ -305,6 +310,8 @@ bail: // Argh! ERROR! Free what we grabbed so far so we can try again. for (int j = 0; j <= i; j++) { + if (views[i].size == 0) + continue; SKIP(flags, views[i].flags); if (views[j].out_ptr_low && *views[j].out_ptr_low) { @@ -334,6 +341,8 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena for (int i = 0; i < num_views; i++) { + if (views[i].size == 0) + continue; SKIP(flags, views[i].flags); if ((views[i].flags & MV_MIRROR_PREVIOUS) == 0) total_mem += roundup(views[i].size); @@ -384,6 +393,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena u8 *base = MemArena::Find4GBBase(); if (!Memory_TryBase(base, views, num_views, flags, arena)) { + ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base."); PanicAlert("MemoryMap_Setup: Failed finding a memory base."); return 0; } @@ -399,6 +409,8 @@ void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemAr { for (int i = 0; i < num_views; i++) { + if (views[i].size == 0) + continue; SKIP(flags, views[i].flags); if (views[i].out_ptr_low && *views[i].out_ptr_low) arena->ReleaseView(*views[i].out_ptr_low, views[i].size); diff --git a/Common/MemArena.h b/Common/MemArena.h index 79165ad8b4..20093770b7 100644 --- a/Common/MemArena.h +++ b/Common/MemArena.h @@ -60,6 +60,8 @@ enum { // MV_FAKE_VMEM = 2, // MV_WII_ONLY = 4, MV_IS_PRIMARY_RAM = 0x100, + MV_IS_EXTRA1_RAM = 0x200, + MV_IS_EXTRA2_RAM = 0x400, }; struct MemoryView diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index a263e21eda..0ac3f07aad 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -45,10 +45,17 @@ #ifdef __SYMBIAN32__ #include -#define SYMBIAN_CODECHUNK_SIZE 1024*1024*20; +#define CODECHUNK_SIZE 1024*1024*20 static RChunk* g_code_chunk = NULL; static RHeap* g_code_heap = NULL; -static void* g_next_ptr = NULL; +static u8* g_next_ptr = NULL; +static u8* g_orig_ptr = NULL; + +void ResetExecutableMemory(void* ptr) +{ + // Just reset the ptr to the base + g_next_ptr = g_orig_ptr; +} #endif // This is purposely not a full wrapper for virtualalloc/mmap, but it @@ -63,14 +70,13 @@ void* AllocateExecutableMemory(size_t size, bool low) //memory chunk for all the executable code for the JIT if( g_code_chunk == NULL && g_code_heap == NULL) { - TInt minsize = SYMBIAN_CODECHUNK_SIZE; - TInt maxsize = SYMBIAN_CODECHUNK_SIZE + 3*GetPageSize(); //some offsets g_code_chunk = new RChunk(); - g_code_chunk->CreateLocalCode(minsize, maxsize); - g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, minsize, 1, maxsize); - g_next_ptr = (void*) g_code_heap->Alloc( minsize ); + g_code_chunk->CreateLocalCode(CODECHUNK_SIZE, CODECHUNK_SIZE + 3*GetPageSize()); + g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, CODECHUNK_SIZE, 1, CODECHUNK_SIZE + 3*GetPageSize()); + g_next_ptr = reinterpret_cast(g_code_heap->AllocZ(CODECHUNK_SIZE)); + g_orig_ptr = g_next_ptr; } - void* ptr = g_next_ptr; + void* ptr = (void*)g_next_ptr; g_next_ptr += size; #else static char *map_hint = 0; @@ -123,7 +129,7 @@ void* AllocateMemoryPages(size_t size) #ifdef _WIN32 void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); #elif defined(__SYMBIAN32__) - void* ptr = new u8[size]; + void* ptr = malloc(size); #else void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); #endif @@ -173,7 +179,7 @@ void FreeMemoryPages(void* ptr, size_t size) PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); ptr = NULL; // Is this our responsibility? #elif defined(__SYMBIAN32__) - delete [] ptr; + free(ptr); #else munmap(ptr, size); #endif diff --git a/Common/MemoryUtil.h b/Common/MemoryUtil.h index 2ae8fea943..67b968a6a4 100644 --- a/Common/MemoryUtil.h +++ b/Common/MemoryUtil.h @@ -30,6 +30,9 @@ void* AllocateAlignedMemory(size_t size,size_t alignment); void FreeAlignedMemory(void* ptr); void WriteProtectMemory(void* ptr, size_t size, bool executable = false); void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false); +#ifdef __SYMBIAN32__ +void ResetExecutableMemory(void* ptr); +#endif inline int GetPageSize() { return 4096; } diff --git a/Common/StdConditionVariable.h b/Common/StdConditionVariable.h deleted file mode 100644 index b6ffd5d424..0000000000 --- a/Common/StdConditionVariable.h +++ /dev/null @@ -1,153 +0,0 @@ - -#ifndef CONDITION_VARIABLE_H_ -#define CONDITION_VARIABLE_H_ - -#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) -#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) - -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !defined(ANDROID) && !defined(__SYMBIAN32__) -// GCC 4.4 provides -#include -#else - -// partial std::condition_variable implementation for win32/pthread - -#include "StdMutex.h" - -#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) -#define USE_RVALUE_REFERENCES -#endif - -#if defined(_WIN32) && defined(_M_X64) -#define USE_CONDITION_VARIABLES -#elif defined(_WIN32) -#define USE_EVENTS -#endif - -namespace std -{ - -class condition_variable -{ -#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) - typedef CONDITION_VARIABLE native_type; -#elif defined(_WIN32) - typedef HANDLE native_type; -#else - typedef pthread_cond_t native_type; -#endif - -public: - -#ifdef USE_EVENTS - typedef native_type native_handle_type; -#else - typedef native_type* native_handle_type; -#endif - - condition_variable() - { -#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) - InitializeConditionVariable(&m_handle); -#elif defined(_WIN32) - m_handle = CreateEvent(NULL, false, false, NULL); -#else - pthread_cond_init(&m_handle, NULL); -#endif - } - - ~condition_variable() - { -#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES) - CloseHandle(m_handle); -#elif !defined(_WIN32) - pthread_cond_destroy(&m_handle); -#endif - } - - condition_variable(const condition_variable&) /*= delete*/; - condition_variable& operator=(const condition_variable&) /*= delete*/; - - void notify_one() - { -#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) - WakeConditionVariable(&m_handle); -#elif defined(_WIN32) - SetEvent(m_handle); -#else - pthread_cond_signal(&m_handle); -#endif - } - - void notify_all() - { -#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) - WakeAllConditionVariable(&m_handle); -#elif defined(_WIN32) - // TODO: broken - SetEvent(m_handle); -#else - pthread_cond_broadcast(&m_handle); -#endif - } - - void wait(unique_lock& lock) - { -#ifdef _WIN32 - #ifdef USE_SRWLOCKS - SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); - #elif defined(USE_CONDITION_VARIABLES) - SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE); - #else - // TODO: broken, the unlock and wait need to be atomic - lock.unlock(); - WaitForSingleObject(m_handle, INFINITE); - lock.lock(); - #endif -#else - pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); -#endif - } - - template - void wait(unique_lock& lock, Predicate pred) - { - while (!pred()) - wait(lock); - } - - //template - //cv_status wait_until(unique_lock& lock, - // const chrono::time_point& abs_time); - - //template - // bool wait_until(unique_lock& lock, - // const chrono::time_point& abs_time, - // Predicate pred); - - //template - //cv_status wait_for(unique_lock& lock, - // const chrono::duration& rel_time); - - //template - // bool wait_for(unique_lock& lock, - // const chrono::duration& rel_time, - // Predicate pred); - - native_handle_type native_handle() - { -#ifdef USE_EVENTS - return m_handle; -#else - return &m_handle; -#endif - } - -private: - native_type m_handle; -}; - -} - -#endif -#endif diff --git a/Common/Thread.cpp b/Common/Thread.cpp deleted file mode 100644 index 2ca3ec08f8..0000000000 --- a/Common/Thread.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Thread.h" -#include "Common.h" - -#ifdef __APPLE__ -#include -#elif defined(ANDROID) -#include -#elif defined BSD4_4 -#include -#endif - -#ifdef BLACKBERRY -#include -#endif - -#ifdef USE_BEGINTHREADEX -#include -#endif - -namespace Common -{ - -int CurrentThreadId() -{ -#ifdef _WIN32 - return GetCurrentThreadId(); -#elif defined __APPLE__ - return mach_thread_self(); -#else - return pthread_self(); -#endif -} - -#ifdef _WIN32 - -bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) -{ - return SetThreadAffinityMask(thread, mask) != 0; -} - -bool SetCurrentThreadAffinity(u32 mask) -{ - return SetThreadAffinityMask(GetCurrentThread(), mask) != 0; -} - -// Supporting functions -void SleepCurrentThread(int ms) -{ - Sleep(ms); -} - -void SwitchCurrentThread() -{ - SwitchToThread(); -} - -// Sets the debugger-visible name of the current thread. -// Uses undocumented (actually, it is now documented) trick. -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp - -// This is implemented much nicer in upcoming msvc++, see: -// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx -void SetCurrentThreadName(const char* szThreadName) -{ - static const DWORD MS_VC_EXCEPTION = 0x406D1388; - - #pragma pack(push,8) - struct THREADNAME_INFO - { - DWORD dwType; // must be 0x1000 - LPCSTR szName; // pointer to name (in user addr space) - DWORD dwThreadID; // thread ID (-1=caller thread) - DWORD dwFlags; // reserved for future use, must be zero - } info; - #pragma pack(pop) - - info.dwType = 0x1000; - info.szName = szThreadName; - info.dwThreadID = -1; //dwThreadID; - info.dwFlags = 0; - - __try - { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); - } - __except(EXCEPTION_CONTINUE_EXECUTION) - {} -} - -void EnableCrashingOnCrashes() -{ - typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); - typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); - const DWORD EXCEPTION_SWALLOWING = 0x1; - - HMODULE kernel32 = LoadLibraryA("kernel32.dll"); - tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, - "GetProcessUserModeExceptionPolicy"); - tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, - "SetProcessUserModeExceptionPolicy"); - if (pGetPolicy && pSetPolicy) - { - DWORD dwFlags; - if (pGetPolicy(&dwFlags)) - { - // Turn off the filter - pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); - } - } -} - - -#else // !WIN32, so must be POSIX threads - -bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) -{ -#ifdef __APPLE__ - return thread_policy_set(pthread_mach_thread_np(thread), - THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1) == 0; -#elif defined(ANDROID) || defined(BLACKBERRY) - return false; -#elif (defined __linux__ || defined BSD4_4) - cpu_set_t cpu_set; - CPU_ZERO(&cpu_set); - - for (int i = 0; i != sizeof(mask) * 8; ++i) { - if ((mask >> i) & 1) - CPU_SET(i, &cpu_set); - } - - return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set) == 0; -#endif - - return false; -} - -bool SetCurrentThreadAffinity(u32 mask) -{ -#ifdef BLACKBERRY - return ThreadCtl(_NTO_TCTL_RUNMASK, &mask) != -1; -#elif defined(ANDROID) - return syscall(__NR_sched_setaffinity, gettid(), sizeof(mask), &mask) == 0; -#else - return SetThreadAffinity(pthread_self(), mask); -#endif -} - -static pthread_key_t threadname_key; -static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; - -void SleepCurrentThread(int ms) -{ - usleep(1000 * ms); -} - -void SwitchCurrentThread() -{ - usleep(1000 * 1); -} - -static void FreeThreadName(void* threadname) -{ - free(threadname); -} - -static void ThreadnameKeyAlloc() -{ - pthread_key_create(&threadname_key, FreeThreadName); -} - -void SetCurrentThreadName(const char* szThreadName) -{ -#ifdef BLACKBERRY - pthread_setname_np(pthread_self(), szThreadName); -#else - pthread_once(&threadname_key_once, ThreadnameKeyAlloc); - - void* threadname; - if ((threadname = pthread_getspecific(threadname_key)) != NULL) - free(threadname); - - pthread_setspecific(threadname_key, strdup(szThreadName)); -#endif - - INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName); -} - -void EnableCrashingOnCrashes() -{ - -} - -#endif - -} // namespace Common diff --git a/Common/Thread.h b/Common/Thread.h deleted file mode 100644 index 0726bef34c..0000000000 --- a/Common/Thread.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _THREAD_H_ -#define _THREAD_H_ - -#include "thread/thread.h" -#include "StdConditionVariable.h" - -// Don't include common.h here as it will break LogManager -#include "CommonTypes.h" -#include -#include - -// This may not be defined outside _WIN32 -#ifndef _WIN32 -#ifndef INFINITE -#define INFINITE 0xffffffff -#endif - -// Assume !ARM && !MIPS = x86 -#if !defined(ARM) && !defined(MIPS) -#include -#endif - -//for gettimeofday and struct time(spec|val) -#include -#include -#endif - -namespace Common -{ - -int CurrentThreadId(); - -// In Windows 7 SP1 or later, stops Windows from swallowing crashes in WndProcs and other callbacks. -void EnableCrashingOnCrashes(); - -bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); -bool SetCurrentThreadAffinity(u32 mask); - -class Event -{ -public: - Event() - : is_set(false) - {}; - - void Set() - { - std::lock_guard lk(m_mutex); - if (!is_set) - { - is_set = true; - m_condvar.notify_one(); - } - } - - void Wait() - { - std::unique_lock lk(m_mutex); - m_condvar.wait(lk, IsSet(this)); - is_set = false; - } - - void Reset() - { - std::unique_lock lk(m_mutex); - // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration - is_set = false; - } - -private: - class IsSet - { - public: - IsSet(const Event* ev) - : m_event(ev) - {} - - bool operator()() - { - return m_event->is_set; - } - - private: - const Event* const m_event; - }; - - volatile bool is_set; - std::condition_variable m_condvar; - std::mutex m_mutex; -}; - -// TODO: doesn't work on windows with (count > 2) -class Barrier -{ -public: - Barrier(size_t count) - : m_count(count), m_waiting(0) - {} - - // block until "count" threads call Sync() - bool Sync() - { - std::unique_lock lk(m_mutex); - - // TODO: broken when next round of Sync()s - // is entered before all waiting threads return from the notify_all - - if (m_count == ++m_waiting) - { - m_waiting = 0; - m_condvar.notify_all(); - return true; - } - else - { - m_condvar.wait(lk, IsDoneWating(this)); - return false; - } - } - -private: - class IsDoneWating - { - public: - IsDoneWating(const Barrier* bar) - : m_bar(bar) - {} - - bool operator()() - { - return (0 == m_bar->m_waiting); - } - - private: - const Barrier* const m_bar; - }; - - std::condition_variable m_condvar; - std::mutex m_mutex; - const size_t m_count; - volatile size_t m_waiting; -}; - -void SleepCurrentThread(int ms); -void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms - -// Use this function during a spin-wait to make the current thread -// relax while another thread is working. This may be more efficient -// than using events because event functions use kernel calls. -inline void YieldCPU() -{ - std::this_thread::yield(); -} - -void SetCurrentThreadName(const char *name); - -} // namespace Common - -#endif // _THREAD_H_ diff --git a/Common/ppcEmitter.h b/Common/ppcEmitter.h index 45156d09e3..64866b0df1 100644 --- a/Common/ppcEmitter.h +++ b/Common/ppcEmitter.h @@ -463,7 +463,7 @@ namespace PpcGen region_size = 0; } - bool IsInSpace(u8 *ptr) + bool IsInSpace(const u8 *ptr) const { return ptr >= region && ptr < region + region_size; } @@ -493,7 +493,7 @@ namespace PpcGen return region; } - size_t GetOffset(u8 *ptr) { + size_t GetOffset(const u8 *ptr) const { return ptr - region; } }; diff --git a/Common/x64Emitter.cpp b/Common/x64Emitter.cpp index 9abc3eff2c..a4e6db829b 100644 --- a/Common/x64Emitter.cpp +++ b/Common/x64Emitter.cpp @@ -1371,6 +1371,12 @@ void XEmitter::PSLLQ(X64Reg reg, int shift) { Write8(shift); } +void XEmitter::PSLLDQ(X64Reg reg, int shift) { + WriteSSEOp(64, 0x73, true, (X64Reg)7, R(reg)); + Write8(shift); +} + + // WARNING not REX compatible void XEmitter::PSRAW(X64Reg reg, int shift) { if (reg > 7) diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index ba7c8d0fa1..182a1992d4 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -126,7 +126,6 @@ enum class XEmitter; -// RIP addressing does not benefit from micro op fusion on Core arch struct OpArg { OpArg() {} // dummy op arg, used for storage @@ -658,6 +657,8 @@ public: void PSLLD(X64Reg reg, int shift); void PSLLQ(X64Reg reg, int shift); + void PSLLDQ(X64Reg reg, int shift); + void PSRAW(X64Reg reg, int shift); void PSRAD(X64Reg reg, int shift); @@ -755,7 +756,7 @@ public: region_size = 0; } - bool IsInSpace(u8 *ptr) + bool IsInSpace(const u8 *ptr) const { return ptr >= region && ptr < region + region_size; } @@ -781,7 +782,7 @@ public: return region; } - size_t GetOffset(u8 *ptr) { + size_t GetOffset(const u8 *ptr) const { return ptr - region; } }; diff --git a/Core/Config.cpp b/Core/Config.cpp index 93be94916b..9661e942c6 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -17,20 +17,31 @@ #include "base/display.h" #include "base/NativeApp.h" +#include "ext/vjson/json.h" +#include "file/ini_file.h" +#include "i18n/i18n.h" +#include "gfx_es2/gpu_features.h" +#include "net/http_client.h" +#include "util/text/parsers.h" + +#include "Common/CPUDetect.h" #include "Common/KeyMap.h" #include "Common/FileUtil.h" #include "Common/StringUtils.h" #include "Config.h" -#include "file/ini_file.h" -#include "i18n/i18n.h" -#include "gfx_es2/gpu_features.h" #include "HLE/sceUtility.h" -#include "Common/CPUDetect.h" + +#ifndef USING_QT_UI +extern const char *PPSSPP_GIT_VERSION; +#endif + +// TODO: Find a better place for this. +http::Downloader g_DownloadManager; Config g_Config; #ifdef IOS -extern bool isJailed; +extern bool iosCanUseJit; #endif Config::Config() { } @@ -52,12 +63,16 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { IniFile::Section *general = iniFile.GetOrCreateSection("General"); general->Get("FirstRun", &bFirstRun, true); + general->Get("RunCount", &iRunCount, 0); + iRunCount++; general->Get("Enable Logging", &bEnableLogging, true); general->Get("AutoRun", &bAutoRun, true); general->Get("Browse", &bBrowse, false); general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true); general->Get("CurrentDirectory", ¤tDirectory, ""); general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false); + general->Get("HomebrewStore", &bHomebrewStore, false); + general->Get("CheckForNewVersion", &bCheckForNewVersion, true); if (!File::Exists(currentDirectory)) currentDirectory = ""; @@ -79,13 +94,13 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { general->Get("RewindFlipFrequency", &iRewindFlipFrequency, 0); general->Get("GridView1", &bGridView1, true); general->Get("GridView2", &bGridView2, true); - general->Get("GridView3", &bGridView3, true); + general->Get("GridView3", &bGridView3, false); // "default" means let emulator decide, "" means disable. general->Get("ReportingHost", &sReportHost, "default"); general->Get("Recent", recentIsos); general->Get("AutoSaveSymbolMap", &bAutoSaveSymbolMap, false); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) general->Get("TopMost", &bTopMost); general->Get("WindowX", &iWindowX, -1); // -1 tells us to center the window. general->Get("WindowY", &iWindowY, -1); @@ -118,19 +133,15 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); #ifdef IOS - cpu->Get("Jit", &bJit, !isJailed); + cpu->Get("Jit", &bJit, iosCanUseJit); #else cpu->Get("Jit", &bJit, true); #endif cpu->Get("SeparateCPUThread", &bSeparateCPUThread, false); cpu->Get("AtomicAudioLocks", &bAtomicAudioLocks, false); -#ifdef __SYMBIAN32__ - cpu->Get("SeparateIOThread", &bSeparateIOThread, false); -#else cpu->Get("SeparateIOThread", &bSeparateIOThread, true); -#endif - cpu->Get("FastMemory", &bFastMemory, false); + cpu->Get("FastMemoryAccess", &bFastMemory, true); cpu->Get("CPUSpeed", &iLockedCPUSpeed, 0); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); @@ -144,12 +155,13 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { graphics->Get("RenderingMode", &iRenderingMode, renderingModeDefault); graphics->Get("SoftwareRendering", &bSoftwareRendering, false); graphics->Get("HardwareTransform", &bHardwareTransform, true); + graphics->Get("SoftwareSkinning", &bSoftwareSkinning, true); graphics->Get("TextureFiltering", &iTexFiltering, 1); - // Auto on Windows, 1x elsewhere. Maybe change to 2x on large screens? -#ifdef _WIN32 + // Auto on Windows, 2x on large screens, 1x elsewhere. +#if defined(_WIN32) && !defined(USING_QT_UI) graphics->Get("InternalResolution", &iInternalResolution, 0); #else - graphics->Get("InternalResolution", &iInternalResolution, 1); + graphics->Get("InternalResolution", &iInternalResolution, pixel_xres >= 1024 ? 2 : 1); #endif graphics->Get("FrameSkip", &iFrameSkip, 0); @@ -169,25 +181,38 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { iAnisotropyLevel = 4; } graphics->Get("VertexCache", &bVertexCache, true); - graphics->Get("VertexDecoderJit", &bVertexDecoderJit, true); +#ifdef IOS + graphics->Get("VertexDecJit", &bVertexDecoderJit, iosCanUseJit); +#else + graphics->Get("VertexDecJit", &bVertexDecoderJit, true); +#endif #ifdef _WIN32 graphics->Get("FullScreen", &bFullScreen, false); #endif + bool partialStretchDefault = false; #ifdef BLACKBERRY - graphics->Get("PartialStretch", &bPartialStretch, pixel_xres == pixel_yres); + partialStretchDefault = pixel_xres < 1.3 * pixel_yres; #endif + graphics->Get("PartialStretch", &bPartialStretch, partialStretchDefault); graphics->Get("StretchToDisplay", &bStretchToDisplay, false); graphics->Get("TrueColor", &bTrueColor, true); - graphics->Get("MipMap", &bMipMap, true); + + graphics->Get("MipMap", &bMipMap, false); + graphics->Get("TexScalingLevel", &iTexScalingLevel, 1); graphics->Get("TexScalingType", &iTexScalingType, 0); graphics->Get("TexDeposterize", &bTexDeposterize, false); graphics->Get("VSyncInterval", &bVSync, false); graphics->Get("DisableStencilTest", &bDisableStencilTest, false); graphics->Get("AlwaysDepthWrite", &bAlwaysDepthWrite, false); +// Has been in use on Symbian since v0.7. Preferred option. +#ifdef __SYMBIAN32__ + graphics->Get("TimerHack", &bTimerHack, true); +#else + graphics->Get("TimerHack", &bTimerHack, false); +#endif graphics->Get("LowQualitySplineBezier", &bLowQualitySplineBezier, false); - graphics->Get("WipeFramebufferAlpha", &bWipeFramebufferAlpha, false); graphics->Get("PostShader", &sPostShaderName, "Off"); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); @@ -233,29 +258,47 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { control->Get("TiltInputType", &iTiltInputType, 0); #endif + control->Get("DisableDpadDiagonals", &bDisableDpadDiagonals, false); + control->Get("TouchButtonStyle", &iTouchButtonStyle, 1); control->Get("TouchButtonOpacity", &iTouchButtonOpacity, 65); - control->Get("ButtonScale", &fButtonScale, 1.15); //set these to -1 if not initialized. initializing these //requires pixel coordinates which is not known right now. //will be initialized in GamepadEmu::CreatePadLayout - control->Get("ActionButtonSpacing", &iActionButtonSpacing, -1); + float defaultScale = 1.15f; + control->Get("ActionButtonSpacing2", &fActionButtonSpacing, 1.0f); control->Get("ActionButtonCenterX", &fActionButtonCenterX, -1.0); control->Get("ActionButtonCenterY", &fActionButtonCenterY, -1.0); - control->Get("DPadRadius", &iDpadRadius, -1); + control->Get("ActionButtonScale", &fActionButtonScale, defaultScale); control->Get("DPadX", &fDpadX, -1.0); control->Get("DPadY", &fDpadY, -1.0); - control->Get("StartKeyX", &fStartKeyX, -1.0); - control->Get("StartKeyY", &fStartKeyY, -1.0); - control->Get("SelectKeyX", &fSelectKeyX, -1.0); - control->Get("SelectKeyY", &fSelectKeyY, -1.0); - control->Get("UnthrottleKeyX", &fUnthrottleKeyX, -1.0); - control->Get("UnthrottleKeyY", &fUnthrottleKeyY, -1.0); - control->Get("LKeyX", &fLKeyX, -1.0); - control->Get("LKeyY", &fLKeyY, -1.0); - control->Get("RKeyX", &fRKeyX, -1.0); - control->Get("RKeyY", &fRKeyY, -1.0); - control->Get("AnalogStickX", &fAnalogStickX, -1.0); - control->Get("AnalogStickY", &fAnalogStickY, -1.0); + + // Check for an old dpad setting + float f; + control->Get("DPadRadius", &f, 0.0f); + if (f > 0.0f) { + ResetControlLayout(); + } else { + control->Get("DPadScale", &fDpadScale, defaultScale); + control->Get("DPadSpacing", &fDpadSpacing, 1.0f); + control->Get("StartKeyX", &fStartKeyX, -1.0); + control->Get("StartKeyY", &fStartKeyY, -1.0); + control->Get("StartKeyScale", &fStartKeyScale, defaultScale); + control->Get("SelectKeyX", &fSelectKeyX, -1.0); + control->Get("SelectKeyY", &fSelectKeyY, -1.0); + control->Get("SelectKeyScale", &fSelectKeyScale, defaultScale); + control->Get("UnthrottleKeyX", &fUnthrottleKeyX, -1.0); + control->Get("UnthrottleKeyY", &fUnthrottleKeyY, -1.0); + control->Get("UnthrottleKeyScale", &fUnthrottleKeyScale, defaultScale); + control->Get("LKeyX", &fLKeyX, -1.0); + control->Get("LKeyY", &fLKeyY, -1.0); + control->Get("LKeyScale", &fLKeyScale, defaultScale); + control->Get("RKeyX", &fRKeyX, -1.0); + control->Get("RKeyY", &fRKeyY, -1.0); + control->Get("RKeyScale", &fRKeyScale, defaultScale); + control->Get("AnalogStickX", &fAnalogStickX, -1.0); + control->Get("AnalogStickY", &fAnalogStickY, -1.0); + control->Get("AnalogStickScale", &fAnalogStickScale, defaultScale); + } // MIGRATION: For users who had the old static touch layout, aren't I nice? if (fDpadX > 1.0 || fDpadY > 1.0) // Likely the rest are too! @@ -277,9 +320,20 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { fAnalogStickX /= dp_xres; fAnalogStickY /= dp_yres; } - + + IniFile::Section *network = iniFile.GetOrCreateSection("Network"); + network->Get("EnableWlan", &bEnableWlan, false); + IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); + pspConfig->Get("PSPModel", &iPSPModel, PSP_MODEL_SLIM); + pspConfig->Get("PSPFirmwareVersion", &iFirmwareVersion, PSP_DEFAULT_FIRMWARE); +#if !defined(_M_X64) && !defined(_WIN32) && !defined(__SYMBIAN32__) + // 32-bit mmap cannot map more than 32MB contiguous + iPSPModel = PSP_MODEL_FAT; +#endif pspConfig->Get("NickName", &sNickName, "PPSSPP"); + pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost"); + pspConfig->Get("MacAddress", &localMacAddress, "01:02:03:04:05:06"); pspConfig->Get("Language", &iLanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD); @@ -288,7 +342,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { pspConfig->Get("ButtonPreference", &iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS); pspConfig->Get("LockParentalLevel", &iLockParentalLevel, 0); pspConfig->Get("WlanAdhocChannel", &iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) pspConfig->Get("BypassOSKWithKeyboard", &bBypassOSKWithKeyboard, false); #endif pspConfig->Get("WlanPowerSave", &bWlanPowerSave, PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF); @@ -311,6 +365,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { debugConfig->Get("ShowBottomTabTitles",&bShowBottomTabTitles,true); debugConfig->Get("ShowDeveloperMenu", &bShowDeveloperMenu, false); debugConfig->Get("SkipDeadbeefFilling", &bSkipDeadbeefFilling, false); + debugConfig->Get("FuncHashMap", &bFuncHashMap, false); IniFile::Section *speedhacks = iniFile.GetOrCreateSection("SpeedHacks"); speedhacks->Get("PrescaleUV", &bPrescaleUV, false); @@ -319,6 +374,25 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { IniFile::Section *jitConfig = iniFile.GetOrCreateSection("JIT"); jitConfig->Get("DiscardRegsOnJRRA", &bDiscardRegsOnJRRA, false); + IniFile::Section *upgrade = iniFile.GetOrCreateSection("Upgrade"); + upgrade->Get("UpgradeMessage", &upgradeMessage, ""); + upgrade->Get("UpgradeVersion", &upgradeVersion, ""); + upgrade->Get("DismissedVersion", &dismissedVersion, ""); + + if (dismissedVersion == upgradeVersion) { + upgradeMessage = ""; + } + + // Check for new version on every 5 runs. + // Sometimes the download may not be finished when the main screen shows (if the user dismisses the + // splash screen quickly), but then we'll just show the notification next time instead, we store the + // upgrade number in the ini. + if (iRunCount % 10 == 0 && bCheckForNewVersion) { + std::shared_ptr dl = g_DownloadManager.StartDownloadWithCallback( + "http://www.ppsspp.org/version.json", "", &DownloadCompletedCallback); + dl->SetHidden(true); + } + INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str()); bSaveSettings = true; @@ -343,10 +417,11 @@ void Config::Save() { } IniFile::Section *general = iniFile.GetOrCreateSection("General"); - + // Need to do this somewhere... bFirstRun = false; general->Set("FirstRun", bFirstRun); + general->Set("RunCount", iRunCount); general->Set("Enable Logging", bEnableLogging); general->Set("AutoRun", bAutoRun); general->Set("Browse", bBrowse); @@ -355,7 +430,7 @@ void Config::Save() { general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad); general->Set("ReportingHost", sReportHost); general->Set("AutoSaveSymbolMap", bAutoSaveSymbolMap); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) general->Set("TopMost", bTopMost); general->Set("WindowX", iWindowX); general->Set("WindowY", iWindowY); @@ -373,10 +448,11 @@ void Config::Save() { general->Set("GridView1", bGridView1); general->Set("GridView2", bGridView2); general->Set("GridView3", bGridView3); - + general->Set("CheckForNewVersion", bCheckForNewVersion); + IniFile::Section *recent = iniFile.GetOrCreateSection("Recent"); recent->Set("MaxRecent", iMaxRecent); - + for (int i = 0; i < iMaxRecent; i++) { char keyName[64]; sprintf(keyName,"FileName%d",i); @@ -384,15 +460,15 @@ void Config::Save() { recent->Set(keyName, recentIsos[i]); } else { recent->Delete(keyName); // delete the nonexisting FileName - } + } } IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Set("Jit", bJit); cpu->Set("SeparateCPUThread", bSeparateCPUThread); - cpu->Set("AtomicAudioLocks", bAtomicAudioLocks); + cpu->Set("AtomicAudioLocks", bAtomicAudioLocks); cpu->Set("SeparateIOThread", bSeparateIOThread); - cpu->Set("FastMemory", bFastMemory); + cpu->Set("FastMemoryAccess", bFastMemory); cpu->Set("CPUSpeed", iLockedCPUSpeed); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); @@ -400,6 +476,7 @@ void Config::Save() { graphics->Set("RenderingMode", iRenderingMode); graphics->Set("SoftwareRendering", bSoftwareRendering); graphics->Set("HardwareTransform", bHardwareTransform); + graphics->Set("SoftwareSkinning", bSoftwareSkinning); graphics->Set("TextureFiltering", iTexFiltering); graphics->Set("InternalResolution", iInternalResolution); graphics->Set("FrameSkip", iFrameSkip); @@ -408,13 +485,10 @@ void Config::Save() { graphics->Set("ForceMaxEmulatedFPS", iForceMaxEmulatedFPS); graphics->Set("AnisotropyLevel", iAnisotropyLevel); graphics->Set("VertexCache", bVertexCache); - graphics->Set("VertexDecoderJit", bVertexDecoderJit); #ifdef _WIN32 graphics->Set("FullScreen", bFullScreen); -#endif -#ifdef BLACKBERRY - graphics->Set("PartialStretch", bPartialStretch); #endif + graphics->Set("PartialStretch", bPartialStretch); graphics->Set("StretchToDisplay", bStretchToDisplay); graphics->Set("TrueColor", bTrueColor); graphics->Set("MipMap", bMipMap); @@ -424,6 +498,7 @@ void Config::Save() { graphics->Set("VSyncInterval", bVSync); graphics->Set("DisableStencilTest", bDisableStencilTest); graphics->Set("AlwaysDepthWrite", bAlwaysDepthWrite); + graphics->Set("TimerHack", bTimerHack); graphics->Set("LowQualitySplineBezier", bLowQualitySplineBezier); graphics->Set("PostShader", sPostShaderName); @@ -448,7 +523,6 @@ void Config::Save() { control->Set("ShowTouchUnthrottle", bShowTouchUnthrottle); control->Set("ShowTouchDpad", bShowTouchDpad); - // control->Set("KeyMapping",iMappingMap); #ifdef USING_GLES2 control->Set("TiltBaseX", fTiltBaseX); control->Set("TiltBaseY", fTiltBaseY); @@ -459,30 +533,46 @@ void Config::Save() { control->Set("DeadzoneRadius", fDeadzoneRadius); control->Set("TiltInputType", iTiltInputType); #endif + control->Set("DisableDpadDiagonals", bDisableDpadDiagonals); + control->Set("TouchButtonStyle", iTouchButtonStyle); control->Set("TouchButtonOpacity", iTouchButtonOpacity); - control->Set("ButtonScale", fButtonScale); - control->Set("ActionButtonSpacing", iActionButtonSpacing); + control->Set("ActionButtonScale", fActionButtonScale); + control->Set("ActionButtonSpacing2", fActionButtonSpacing); control->Set("ActionButtonCenterX", fActionButtonCenterX); control->Set("ActionButtonCenterY", fActionButtonCenterY); - control->Set("DPadRadius", iDpadRadius); control->Set("DPadX", fDpadX); control->Set("DPadY", fDpadY); + control->Set("DPadScale", fDpadScale); + control->Set("DPadSpacing", fDpadSpacing); control->Set("StartKeyX", fStartKeyX); control->Set("StartKeyY", fStartKeyY); + control->Set("StartKeyScale", fStartKeyScale); control->Set("SelectKeyX", fSelectKeyX); control->Set("SelectKeyY", fSelectKeyY); + control->Set("SelectKeyScale", fSelectKeyScale); control->Set("UnthrottleKeyX", fUnthrottleKeyX); control->Set("UnthrottleKeyY", fUnthrottleKeyY); + control->Set("UnthrottleKeyScale", fUnthrottleKeyScale); control->Set("LKeyX", fLKeyX); control->Set("LKeyY", fLKeyY); + control->Set("LKeyScale", fLKeyScale); control->Set("RKeyX", fRKeyX); control->Set("RKeyY", fRKeyY); + control->Set("RKeyScale", fRKeyScale); control->Set("AnalogStickX", fAnalogStickX); control->Set("AnalogStickY", fAnalogStickY); + control->Set("AnalogStickScale", fAnalogStickScale); + control->Delete("DPadRadius"); + IniFile::Section *network = iniFile.GetOrCreateSection("Network"); + network->Set("EnableWlan", bEnableWlan); IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); + pspConfig->Set("PSPModel", iPSPModel); + pspConfig->Set("PSPFirmwareVersion", iFirmwareVersion); pspConfig->Set("NickName", sNickName.c_str()); + pspConfig->Set("proAdhocServer", proAdhocServer.c_str()); + pspConfig->Set("MacAddress", localMacAddress.c_str()); pspConfig->Set("Language", iLanguage); pspConfig->Set("TimeFormat", iTimeFormat); pspConfig->Set("DateFormat", iDateFormat); @@ -493,7 +583,7 @@ void Config::Save() { pspConfig->Set("WlanAdhocChannel", iWlanAdhocChannel); pspConfig->Set("WlanPowerSave", bWlanPowerSave); pspConfig->Set("EncryptSave", bEncryptSave); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) pspConfig->Set("BypassOSKWithKeyboard", bBypassOSKWithKeyboard); #endif @@ -514,11 +604,18 @@ void Config::Save() { debugConfig->Set("ShowBottomTabTitles",bShowBottomTabTitles); debugConfig->Set("ShowDeveloperMenu", bShowDeveloperMenu); debugConfig->Set("SkipDeadbeefFilling", bSkipDeadbeefFilling); + debugConfig->Set("FuncHashMap", bFuncHashMap); IniFile::Section *speedhacks = iniFile.GetOrCreateSection("SpeedHacks"); speedhacks->Set("PrescaleUV", bPrescaleUV); speedhacks->Set("DisableAlphaTest", bDisableAlphaTest); + // Save upgrade check state + IniFile::Section *upgrade = iniFile.GetOrCreateSection("Upgrade"); + upgrade->Set("UpgradeMessage", upgradeMessage); + upgrade->Set("UpgradeVersion", upgradeVersion); + upgrade->Set("DismissedVersion", dismissedVersion); + if (!iniFile.Save(iniFilename_.c_str())) { ERROR_LOG(LOADER, "Error saving config - can't write ini %s", iniFilename_.c_str()); return; @@ -542,9 +639,67 @@ void Config::Save() { } } +// Use for debugging the version check without messing with the server +#if 0 +#define PPSSPP_GIT_VERSION "v0.0.1-gaaaaaaaaa" +#endif + +void Config::DownloadCompletedCallback(http::Download &download) { + if (download.ResultCode() != 200) { + ERROR_LOG(LOADER, "Failed to download version.json"); + return; + } + std::string data; + download.buffer().TakeAll(&data); + if (data.empty()) { + ERROR_LOG(LOADER, "Version check: Empty data from server!"); + return; + } + + JsonReader reader(data.c_str(), data.size()); + const json_value *root = reader.root(); + std::string version = root->getString("version", ""); + + const char *gitVer = PPSSPP_GIT_VERSION; + Version installed(gitVer); + Version upgrade(version); + Version dismissed(g_Config.dismissedVersion); + + if (!installed.IsValid()) { + ERROR_LOG(LOADER, "Version check: Local version string invalid. Build problems? %s", PPSSPP_GIT_VERSION); + return; + } + if (!upgrade.IsValid()) { + ERROR_LOG(LOADER, "Version check: Invalid server version: %s", version.c_str()); + return; + } + + if (installed >= upgrade) { + INFO_LOG(LOADER, "Version check: Already up to date, erasing any upgrade message"); + g_Config.upgradeMessage = ""; + g_Config.upgradeVersion = upgrade.ToString(); + g_Config.dismissedVersion = ""; + return; + } + + if (installed < upgrade && dismissed != upgrade) { + g_Config.upgradeMessage = "New version of PPSSPP available!"; + g_Config.upgradeVersion = upgrade.ToString(); + g_Config.dismissedVersion = ""; + } +} + +void Config::DismissUpgrade() { + g_Config.dismissedVersion = g_Config.upgradeVersion; +} + void Config::AddRecent(const std::string &file) { - for (auto str = recentIsos.begin(); str != recentIsos.end(); str++) { - if (*str == file) { + for (auto str = recentIsos.begin(); str != recentIsos.end(); ++str) { +#ifdef _WIN32 + if (!strcmpIgnore((*str).c_str(), file.c_str(), "\\", "/")) { +#else + if (!strcmp((*str).c_str(), file.c_str())) { +#endif recentIsos.erase(str); recentIsos.insert(recentIsos.begin(), file); if ((int)recentIsos.size() > iMaxRecent) @@ -560,15 +715,15 @@ void Config::AddRecent(const std::string &file) { void Config::CleanRecent() { std::vector cleanedRecent; for (size_t i = 0; i < recentIsos.size(); i++) { - if (File::Exists(recentIsos[i])){ + if (File::Exists(recentIsos[i])) { // clean the redundant recent games' list. - if (cleanedRecent.size()==0){ // add first one - cleanedRecent.push_back(recentIsos[i]); + if (cleanedRecent.size()==0) { // add first one + cleanedRecent.push_back(recentIsos[i]); } - for (size_t j=0; j recentIsos; std::string sLanguageIni; + // GFX bool bSoftwareRendering; bool bHardwareTransform; // only used in the GLES backend + bool bSoftwareSkinning; // may speed up some games + int iRenderingMode; // 0 = non-buffered rendering 1 = buffered rendering 2 = Read Framebuffer to memory (CPU) 3 = Read Framebuffer to memory (GPU) int iTexFiltering; // 1 = off , 2 = nearest , 3 = linear , 4 = linear(CG) -#ifdef BLACKBERRY bool bPartialStretch; -#endif bool bStretchToDisplay; bool bVSync; int iFrameSkip; @@ -99,8 +115,8 @@ public: bool bReloadCheats; bool bDisableStencilTest; bool bAlwaysDepthWrite; + bool bTimerHack; bool bLowQualitySplineBezier; - bool bWipeFramebufferAlpha; // this was meant to be CopyStencilToAlpha but not done yet. std::string sPostShaderName; // Off for off. // Sound @@ -135,26 +151,42 @@ public: bool bGridView2; bool bGridView3; + // Disable diagonals + bool bDisableDpadDiagonals; + // Control Style + int iTouchButtonStyle; // Control Positions int iTouchButtonOpacity; - float fButtonScale; //space between PSP buttons - int iActionButtonSpacing; //the PSP button's center (triangle, circle, square, cross) float fActionButtonCenterX, fActionButtonCenterY; + float fActionButtonScale; + float fActionButtonSpacing; //radius of the D-pad (PSP cross) - int iDpadRadius; + // int iDpadRadius; //the D-pad (PSP cross) position float fDpadX, fDpadY; + float fDpadScale; + float fDpadSpacing; //the start key position float fStartKeyX, fStartKeyY; - //the select key position; + float fStartKeyScale; + //the select key position; float fSelectKeyX, fSelectKeyY; + float fSelectKeyScale; + float fUnthrottleKeyX, fUnthrottleKeyY; + float fUnthrottleKeyScale; + float fLKeyX, fLKeyY; + float fLKeyScale; + float fRKeyX, fRKeyY; + float fRKeyScale; + //position of the analog stick float fAnalogStickX, fAnalogStickY; + float fAnalogStickScale; // Controls Visibility bool bShowTouchControls; @@ -170,10 +202,10 @@ public: bool bShowTouchLTrigger; bool bShowTouchRTrigger; - + bool bShowTouchAnalogStick; bool bShowTouchDpad; - + bool bHapticFeedback; // GLES backend-specific hacks. Not saved to the ini file, do not add checkboxes. Will be made into @@ -193,6 +225,8 @@ public: // SystemParam std::string sNickName; + std::string proAdhocServer; + std::string localMacAddress; int iLanguage; int iTimeFormat; int iDateFormat; @@ -201,10 +235,16 @@ public: int iButtonPreference; int iLockParentalLevel; bool bEncryptSave; + + // Networking + bool bEnableWlan; int iWlanAdhocChannel; bool bWlanPowerSave; + + int iPSPModel; + int iFirmwareVersion; // TODO: Make this work with your platform, too! -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) bool bBypassOSKWithKeyboard; #endif @@ -226,6 +266,7 @@ public: bool bShowDeveloperMenu; // Double edged sword: much easier debugging, but not accurate. bool bSkipDeadbeefFilling; + bool bFuncHashMap; std::string currentDirectory; std::string externalDirectory; @@ -233,6 +274,11 @@ public: std::string flash0Directory; std::string internalDataDirectory; + // Data for upgrade prompt + std::string upgradeMessage; // The actual message from the server is currently not used, need a translation mechanism. So this just acts as a flag. + std::string upgradeVersion; + std::string dismissedVersion; + void Load(const char *iniFileName = "ppsspp.ini", const char *controllerIniFilename = "controls.ini"); void Save(); void RestoreDefaults(); @@ -247,6 +293,11 @@ public: void AddRecent(const std::string &file); void CleanRecent(); + static void DownloadCompletedCallback(http::Download &download); + void DismissUpgrade(); + + void ResetControlLayout(); + private: std::string iniFilename_; std::string controllerIniFilename_; @@ -254,4 +305,7 @@ private: std::string defaultPath_; }; +// TODO: Find a better place for this. +extern http::Downloader g_DownloadManager; extern Config g_Config; + diff --git a/Core/Core.cpp b/Core/Core.cpp index 53db613311..f4064c4f75 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -145,7 +145,7 @@ void Core_RunLoop() { while (globalUIState != UISTATE_INGAME && globalUIState != UISTATE_EXIT) { time_update(); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) double startTime = time_now_d(); UpdateRunLoop(); @@ -164,7 +164,7 @@ void Core_RunLoop() { while (!coreState && globalUIState == UISTATE_INGAME) { time_update(); UpdateRunLoop(); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) if (!Core_IsStepping()) { GL_SwapBuffers(); } diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 66ebeb938a..3fd32fd53d 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -171,6 +171,7 @@ + @@ -194,6 +195,7 @@ + @@ -390,6 +392,7 @@ + @@ -423,6 +426,7 @@ + @@ -449,6 +453,7 @@ + @@ -518,6 +523,12 @@ true true + + true + true + true + true + true true @@ -575,6 +586,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 7e8ba76570..715e6ec4f0 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -496,6 +496,15 @@ Dialog + + Debugger + + + HLE\Libraries + + + Util + @@ -915,6 +924,18 @@ MIPS\JitCommon + + MIPS\ARM + + + Debugger + + + HLE\Libraries + + + Util + @@ -922,4 +943,4 @@ - \ No newline at end of file + diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 2cf0112055..27acc60e36 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -33,7 +33,7 @@ enum GPUCore { // PSP_CoreParameter() struct CoreParameter { - CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true) {} + CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true), freezeNext(false), frozen(false) {} CPUCore cpuCore; GPUCore gpuCore; bool enableSound; // there aren't multiple sound cores. @@ -64,4 +64,8 @@ struct CoreParameter { int fpsLimit; bool updateRecent; + + // Freeze-frame. For nvidia perfhud profiling. Developers only. + bool freezeNext; + bool frozen; }; diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index b9867e9908..1d81b248dd 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -24,8 +24,10 @@ #include "Atomics.h" #include "CoreTiming.h" #include "Core.h" +#include "Config.h" #include "HLE/sceKernelThread.h" #include "../Common/ChunkFile.h" +#include "HLE/sceDisplay.h" int CPU_HZ = 222000000; @@ -100,14 +102,29 @@ int GetClockFrequencyMHz() return CPU_HZ / 1000000; } +u64 GetGlobalTimeUsScaled() +{ + s64 ticksSinceLast = GetTicks() - lastGlobalTimeTicks; + int freq = GetClockFrequencyMHz(); + if (g_Config.bTimerHack) { + float vps; + __DisplayGetVPS(&vps); + if (vps > 4.0f) + freq *= (vps / 60.0f); + } + s64 usSinceLast = ticksSinceLast / freq; + return lastGlobalTimeUs + usSinceLast; + +} + u64 GetGlobalTimeUs() { s64 ticksSinceLast = GetTicks() - lastGlobalTimeTicks; - s64 usSinceLast = ticksSinceLast / GetClockFrequencyMHz(); + int freq = GetClockFrequencyMHz(); + s64 usSinceLast = ticksSinceLast / freq; return lastGlobalTimeUs + usSinceLast; } - Event* GetNewEvent() { if(!eventPool) diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index 8c53987e3a..03a10f2e05 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -80,6 +80,7 @@ namespace CoreTiming u64 GetTicks(); u64 GetIdleTicks(); u64 GetGlobalTimeUs(); + u64 GetGlobalTimeUsScaled(); // Returns the event_type identifier. int RegisterEvent(const char *name, TimedCallback callback); diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 4d82886c99..2c4ada35f3 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -114,7 +114,10 @@ void CWCheatEngine::CreateCodeList() { //Creates code list to be used in functio continue; //Line indicates Disc ID, not needed for cheats } if (initialCodesList[i].substr(0,2) == "_G") { - continue; //Line indicates game Title, also not needed for cheats. + continue; //Line indicates game Title, also not needed for cheats + } + if (initialCodesList[i].substr(0,2) == "//") { + continue; //Line indicates comment, also not needed for cheats. } if (initialCodesList[i].substr(0,3) == "_C1") { cheatEnabled = true; @@ -231,7 +234,7 @@ std::vector CWCheatEngine::GetCodesList() { //Reads the entire chea } for (int i = 0; !list.eof(); i ++) { getline(list, line, '\n'); - if (line.length() > 3 && line.substr(0,1) == "_"){ + if (line.length() > 3 && (line.substr(0,1) == "_"||line.substr(0,2) == "//")){ codesList.push_back(line); } } diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 48826a095c..fa416b8c3e 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -324,13 +324,24 @@ const std::vector CBreakPoints::GetBreakpoints() void CBreakPoints::Update(u32 addr) { - if (MIPSComp::jit && Core_IsInactive()) + if (MIPSComp::jit) { + bool resume = false; + if (Core_IsStepping() == false) + { + Core_EnableStepping(true); + Core_WaitInactive(); + resume = true; + } + // In case this is a delay slot, clear the previous instruction too. if (addr != 0) MIPSComp::jit->ClearCacheAt(addr - 4, 8); else MIPSComp::jit->ClearCache(); + + if (resume) + Core_EnableStepping(false); } // Redraw in order to show the breakpoint. diff --git a/Core/Debugger/DebugInterface.h b/Core/Debugger/DebugInterface.h index 7a000d4df9..12605c86b5 100644 --- a/Core/Debugger/DebugInterface.h +++ b/Core/Debugger/DebugInterface.h @@ -41,8 +41,6 @@ public: virtual void runToBreakpoint() {} virtual int getColor(unsigned int address){return 0xFFFFFFFF;} virtual const char *getDescription(unsigned int address) {return "";} - virtual const char *findSymbolForAddress(unsigned int address) { return NULL; }; - virtual bool getSymbolValue(char* symbol, u32& dest) { return false; }; virtual bool initExpression(const char* exp, PostfixExpression& dest) { return false; }; virtual bool parseExpression(PostfixExpression& exp, u32& dest) { return false; }; diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp new file mode 100644 index 0000000000..ac72137c12 --- /dev/null +++ b/Core/Debugger/DisassemblyManager.cpp @@ -0,0 +1,1004 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "DisassemblyManager.h" +#include "DebugInterface.h" +#include "Core/Debugger/SymbolMap.h" +#include "Core/MIPS/MIPSCodeUtils.h" +#include "Core/MIPS/MIPSTables.h" +#include "Common/Common.h" +#include "ext/xxhash.h" + +#include + +std::map DisassemblyManager::entries; +DebugInterface* DisassemblyManager::cpu; +int DisassemblyManager::maxParamChars = 29; + +bool isInInterval(u32 start, u32 size, u32 value) +{ + return start <= value && value <= (start+size-1); +} + + +static u32 computeHash(u32 address, u32 size) +{ + return XXH32(Memory::GetPointer(address),size,0xBACD7814); +} + + +void parseDisasm(const char* disasm, char* opcode, char* arguments, bool insertSymbols) +{ + // copy opcode + while (*disasm != 0 && *disasm != '\t') + { + *opcode++ = *disasm++; + } + *opcode = 0; + + if (*disasm++ == 0) + { + *arguments = 0; + return; + } + + const char* jumpAddress = strstr(disasm,"->$"); + const char* jumpRegister = strstr(disasm,"->"); + while (*disasm != 0) + { + // parse symbol + if (disasm == jumpAddress) + { + u32 branchTarget; + sscanf(disasm+3,"%08x",&branchTarget); + + const char* addressSymbol = symbolMap.GetLabelName(branchTarget); + if (addressSymbol != NULL && insertSymbols) + { + arguments += sprintf(arguments,"%s",addressSymbol); + } else { + arguments += sprintf(arguments,"0x%08X",branchTarget); + } + + disasm += 3+8; + continue; + } + + if (disasm == jumpRegister) + disasm += 2; + + if (*disasm == ' ') + { + disasm++; + continue; + } + *arguments++ = *disasm++; + } + + *arguments = 0; +} + +std::map::iterator findDisassemblyEntry(std::map& entries, u32 address, bool exact) +{ + if (exact) + return entries.find(address); + + if (entries.size() == 0) + return entries.end(); + + // find first elem that's >= address + auto it = entries.lower_bound(address); + if (it != entries.end()) + { + // it may be an exact match + if (isInInterval(it->second->getLineAddress(0),it->second->getTotalSize(),address)) + return it; + + // otherwise it may point to the next + if (it != entries.begin()) + { + it--; + if (isInInterval(it->second->getLineAddress(0),it->second->getTotalSize(),address)) + return it; + } + } + + // check last entry manually + auto rit = entries.rbegin(); + if (isInInterval(rit->second->getLineAddress(0),rit->second->getTotalSize(),address)) + { + return (++rit).base(); + } + + // no match otherwise + return entries.end(); +} + +void DisassemblyManager::analyze(u32 address, u32 size = 1024) +{ + u32 end = address+size; + + address &= ~3; + u32 start = address; + + while (address < end && start <= address) + { + if (!PSP_IsInited()) + return; + + auto it = findDisassemblyEntry(entries,address,false); + if (it != entries.end()) + { + DisassemblyEntry* entry = it->second; + entry->recheck(); + address = entry->getLineAddress(0)+entry->getTotalSize(); + continue; + } + + SymbolInfo info; + if (!symbolMap.GetSymbolInfo(&info,address,ST_ALL)) + { + if (address % 4) + { + u32 next = std::min((address+3) & ~3,symbolMap.GetNextSymbolAddress(address,ST_ALL)); + DisassemblyData* data = new DisassemblyData(address,next-address,DATATYPE_BYTE); + entries[address] = data; + address = next; + continue; + } + + u32 next = symbolMap.GetNextSymbolAddress(address,ST_ALL); + + if ((next % 4) && next != -1) + { + u32 alignedNext = next & ~3; + + if (alignedNext != address) + { + DisassemblyOpcode* opcode = new DisassemblyOpcode(address,(alignedNext-address)/4); + entries[address] = opcode; + } + + DisassemblyData* data = new DisassemblyData(address,next-alignedNext,DATATYPE_BYTE); + entries[alignedNext] = data; + } else { + DisassemblyOpcode* opcode = new DisassemblyOpcode(address,(next-address)/4); + entries[address] = opcode; + } + + address = next; + continue; + } + + switch (info.type) + { + case ST_FUNCTION: + { + DisassemblyFunction* function = new DisassemblyFunction(info.address,info.size); + entries[info.address] = function; + address = info.address+info.size; + } + break; + case ST_DATA: + { + DisassemblyData* data = new DisassemblyData(info.address,info.size,symbolMap.GetDataType(info.address)); + entries[info.address] = data; + address = info.address+info.size; + } + break; + } + } + +} + +std::vector DisassemblyManager::getBranchLines(u32 start, u32 size) +{ + std::vector result; + + auto it = findDisassemblyEntry(entries,start,false); + if (it != entries.end()) + { + do + { + it->second->getBranchLines(start,size,result); + it++; + } while (it != entries.end() && start+size > it->second->getLineAddress(0)); + } + + return result; +} + +void DisassemblyManager::getLine(u32 address, bool insertSymbols, DisassemblyLineInfo& dest) +{ + auto it = findDisassemblyEntry(entries,address,false); + if (it == entries.end()) + { + analyze(address); + it = findDisassemblyEntry(entries,address,false); + + if (it == entries.end()) + { + if (address % 4) + dest.totalSize = ((address+3) & ~3)-address; + else + dest.totalSize = 4; + dest.name = "ERROR"; + dest.params = "Disassembly failure"; + return; + } + } + + DisassemblyEntry* entry = it->second; + if (entry->disassemble(address,dest,insertSymbols)) + return; + + if (address % 4) + dest.totalSize = ((address+3) & ~3)-address; + else + dest.totalSize = 4; + dest.name = "ERROR"; + dest.params = "Disassembly failure"; +} + +u32 DisassemblyManager::getStartAddress(u32 address) +{ + auto it = findDisassemblyEntry(entries,address,false); + if (it == entries.end()) + { + analyze(address); + it = findDisassemblyEntry(entries,address,false); + if (it == entries.end()) + return address; + } + + DisassemblyEntry* entry = it->second; + int line = entry->getLineNum(address,true); + return entry->getLineAddress(line); +} + +u32 DisassemblyManager::getNthPreviousAddress(u32 address, int n) +{ + while (Memory::IsValidAddress(address)) + { + auto it = findDisassemblyEntry(entries,address,false); + + while (it != entries.end()) + { + DisassemblyEntry* entry = it->second; + int oldLineNum = entry->getLineNum(address,true); + int oldNumLines = entry->getNumLines(); + if (n <= oldLineNum) + { + return entry->getLineAddress(oldLineNum-n); + } + + address = entry->getLineAddress(0)-1; + n -= oldLineNum+1; + it = findDisassemblyEntry(entries,address,false); + } + + analyze(address-127,128); + } + + return address-n*4; +} + +u32 DisassemblyManager::getNthNextAddress(u32 address, int n) +{ + while (Memory::IsValidAddress(address)) + { + auto it = findDisassemblyEntry(entries,address,false); + + while (it != entries.end()) + { + DisassemblyEntry* entry = it->second; + int oldLineNum = entry->getLineNum(address,true); + int oldNumLines = entry->getNumLines(); + if (oldLineNum+n < oldNumLines) + { + return entry->getLineAddress(oldLineNum+n); + } + + address = entry->getLineAddress(0)+entry->getTotalSize(); + n -= (oldNumLines-oldLineNum); + it = findDisassemblyEntry(entries,address,false); + } + + analyze(address); + } + + return address+n*4; +} + +void DisassemblyManager::clear() +{ + for (auto it = entries.begin(); it != entries.end(); it++) + { + delete it->second; + } + entries.clear(); +} + +DisassemblyFunction::DisassemblyFunction(u32 _address, u32 _size): address(_address), size(_size) +{ + hash = computeHash(address,size); + load(); +} + +void DisassemblyFunction::recheck() +{ + u32 newHash = computeHash(address,size); + if (hash != newHash) + { + hash = newHash; + clear(); + load(); + } +} + +int DisassemblyFunction::getNumLines() +{ + return (int) lineAddresses.size(); +} + +int DisassemblyFunction::getLineNum(u32 address, bool findStart) +{ + if (findStart) + { + int last = (int)lineAddresses.size() - 1; + for (int i = 0; i < last; i++) + { + u32 next = lineAddresses[i + 1]; + if (lineAddresses[i] <= address && next > address) + return i; + } + if (lineAddresses[last] <= address && this->address + this->size > address) + return last; + } + else + { + int last = (int)lineAddresses.size() - 1; + for (int i = 0; i < last; i++) + { + u32 next = lineAddresses[i + 1]; + if (lineAddresses[i] == address) + return i; + } + if (lineAddresses[last] == address) + return last; + } + + return 0; +} + +u32 DisassemblyFunction::getLineAddress(int line) +{ + return lineAddresses[line]; +} + +bool DisassemblyFunction::disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) +{ + auto it = findDisassemblyEntry(entries,address,false); + if (it == entries.end()) + return false; + + return it->second->disassemble(address,dest,insertSymbols); +} + +void DisassemblyFunction::getBranchLines(u32 start, u32 size, std::vector& dest) +{ + u32 end = start+size; + + for (size_t i = 0; i < lines.size(); i++) + { + BranchLine& line = lines[i]; + + u32 first = line.first; + u32 second = line.second; + + // skip branches that are entirely before or entirely after the window + if ((first < start && second < start) || + (first > end && second > end)) + continue; + + dest.push_back(line); + } +} + +#define NUM_LANES 16 + +void DisassemblyFunction::generateBranchLines() +{ + struct LaneInfo + { + bool used; + u32 end; + }; + + LaneInfo lanes[NUM_LANES]; + for (int i = 0; i < NUM_LANES; i++) + lanes[i].used = false; + + u32 end = address+size; + + DebugInterface* cpu = DisassemblyManager::getCpu(); + for (u32 funcPos = address; funcPos < end; funcPos += 4) + { + MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos); + + bool inFunction = (opInfo.branchTarget >= address && opInfo.branchTarget < end); + if (opInfo.isBranch && !opInfo.isBranchToRegister && !opInfo.isLinkedBranch && inFunction) + { + BranchLine line; + if (opInfo.branchTarget < funcPos) + { + line.first = opInfo.branchTarget; + line.second = funcPos; + line.type = LINE_UP; + } else { + line.first = funcPos; + line.second = opInfo.branchTarget; + line.type = LINE_DOWN; + } + + lines.push_back(line); + } + } + + std::sort(lines.begin(),lines.end()); + for (size_t i = 0; i < lines.size(); i++) + { + for (int l = 0; l < NUM_LANES; l++) + { + if (lines[i].first > lanes[l].end) + lanes[l].used = false; + } + + int lane = -1; + for (int l = 0; l < NUM_LANES; l++) + { + if (lanes[l].used == false) + { + lane = l; + break; + } + } + + if (lane == -1) + { + // error + continue; + } + + lanes[lane].end = lines[i].second; + lanes[lane].used = true; + lines[i].laneIndex = lane; + } +} + +void DisassemblyFunction::addOpcodeSequence(u32 start, u32 end) +{ + DisassemblyOpcode* opcode = new DisassemblyOpcode(start,(end-start)/4); + entries[start] = opcode; + for (u32 pos = start; pos < end; pos += 4) + { + lineAddresses.push_back(pos); + } +} + +void DisassemblyFunction::load() +{ + generateBranchLines(); + + // gather all branch targets + std::set branchTargets; + for (size_t i = 0; i < lines.size(); i++) + { + switch (lines[i].type) + { + case LINE_DOWN: + branchTargets.insert(lines[i].second); + break; + case LINE_UP: + branchTargets.insert(lines[i].first); + break; + } + } + + DebugInterface* cpu = DisassemblyManager::getCpu(); + u32 funcPos = address; + u32 funcEnd = address+size; + + u32 nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); + u32 opcodeSequenceStart = funcPos; + while (funcPos < funcEnd) + { + if (funcPos == nextData) + { + if (opcodeSequenceStart != funcPos) + addOpcodeSequence(opcodeSequenceStart,funcPos); + + DisassemblyData* data = new DisassemblyData(funcPos,symbolMap.GetDataSize(funcPos),symbolMap.GetDataType(funcPos)); + entries[funcPos] = data; + lineAddresses.push_back(funcPos); + funcPos += data->getTotalSize(); + + nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); + opcodeSequenceStart = funcPos; + continue; + } + + // force align + if (funcPos % 4) + { + u32 nextPos = (funcPos+3) & ~3; + + DisassemblyComment* comment = new DisassemblyComment(funcPos,nextPos-funcPos,".align","4"); + entries[funcPos] = comment; + lineAddresses.push_back(funcPos); + + funcPos = nextPos; + opcodeSequenceStart = funcPos; + continue; + } + + MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos); + u32 opAddress = funcPos; + funcPos += 4; + + // skip branches and their delay slots + if (opInfo.isBranch) + { + funcPos += 4; + continue; + } + + // lui + if (MIPS_GET_OP(opInfo.encodedOpcode) == 0x0F && funcPos < funcEnd && funcPos != nextData) + { + MIPSOpcode next = Memory::Read_Instruction(funcPos); + MIPSInfo nextInfo = MIPSGetInfo(next); + + u32 immediate = ((opInfo.encodedOpcode & 0xFFFF) << 16) + (s16)(next.encoding & 0xFFFF); + int rt = MIPS_GET_RT(opInfo.encodedOpcode); + + int nextRs = MIPS_GET_RS(next.encoding); + int nextRt = MIPS_GET_RT(next.encoding); + + // both rs and rt of the second op have to match rt of the first, + // otherwise there may be hidden consequences if the macro is displayed. + // also, don't create a macro if something branches into the middle of it + if (nextRs == rt && nextRt == rt && branchTargets.find(funcPos) == branchTargets.end()) + { + DisassemblyMacro* macro = NULL; + switch (MIPS_GET_OP(next.encoding)) + { + case 0x09: // addiu + macro = new DisassemblyMacro(opAddress); + macro->setMacroLi(immediate,rt); + funcPos += 4; + break; + case 0x20: // lb + case 0x21: // lh + case 0x23: // lw + case 0x24: // lbu + case 0x25: // lhu + case 0x28: // sb + case 0x29: // sh + case 0x2B: // sw + macro = new DisassemblyMacro(opAddress); + + int dataSize; + switch (nextInfo & MEMTYPE_MASK) { + case MEMTYPE_BYTE: + dataSize = 1; + break; + case MEMTYPE_HWORD: + dataSize = 2; + break; + case MEMTYPE_WORD: + case MEMTYPE_FLOAT: + dataSize = 4; + break; + case MEMTYPE_VQUAD: + dataSize = 16; + break; + } + + macro->setMacroMemory(MIPSGetName(next),immediate,rt,dataSize); + funcPos += 4; + break; + } + + if (macro != NULL) + { + if (opcodeSequenceStart != opAddress) + addOpcodeSequence(opcodeSequenceStart,opAddress); + + entries[opAddress] = macro; + for (int i = 0; i < macro->getNumLines(); i++) + { + lineAddresses.push_back(macro->getLineAddress(i)); + } + + opcodeSequenceStart = funcPos; + continue; + } + } + } + + // just a normal opcode + } + + if (opcodeSequenceStart != funcPos) + addOpcodeSequence(opcodeSequenceStart,funcPos); +} + +void DisassemblyFunction::clear() +{ + for (auto it = entries.begin(); it != entries.end(); it++) + { + delete it->second; + } + + entries.clear(); + lines.clear(); + lineAddresses.clear(); + hash = 0; +} + +bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) +{ + char opcode[64],arguments[256]; + const char *dizz = DisassemblyManager::getCpu()->disasm(address,4); + parseDisasm(dizz,opcode,arguments,insertSymbols); + dest.type = DISTYPE_OPCODE; + dest.name = opcode; + dest.params = arguments; + dest.totalSize = 4; + dest.info = MIPSAnalyst::GetOpcodeInfo(DisassemblyManager::getCpu(),address); + return true; +} + +void DisassemblyOpcode::getBranchLines(u32 start, u32 size, std::vector& dest) +{ + if (start < address) + { + size = start+size-address; + start = address; + } + + if (start+size > address+num*4) + size = address+num*4-start; + + int lane = 0; + for (u32 pos = start; pos < start+size; pos += 4) + { + MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(DisassemblyManager::getCpu(),pos); + if (info.isBranch && !info.isBranchToRegister && !info.isLinkedBranch) + { + BranchLine line; + line.laneIndex = lane++; + + if (info.branchTarget < pos) + { + line.first = info.branchTarget; + line.second = pos; + line.type = LINE_UP; + } else { + line.first = pos; + line.second = info.branchTarget; + line.type = LINE_DOWN; + } + + dest.push_back(line); + } + } +} + + +void DisassemblyMacro::setMacroLi(u32 _immediate, u8 _rt) +{ + type = MACRO_LI; + name = "li"; + immediate = _immediate; + rt = _rt; + numOpcodes = 2; +} + +void DisassemblyMacro::setMacroMemory(std::string _name, u32 _immediate, u8 _rt, int _dataSize) +{ + type = MACRO_MEMORYIMM; + name = _name; + immediate = _immediate; + rt = _rt; + dataSize = _dataSize; + numOpcodes = 2; +} + +bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) +{ + char buffer[64]; + dest.type = DISTYPE_MACRO; + dest.info = MIPSAnalyst::GetOpcodeInfo(DisassemblyManager::getCpu(),address); + + const char* addressSymbol; + switch (type) + { + case MACRO_LI: + dest.name = name; + + addressSymbol = symbolMap.GetLabelName(immediate); + if (addressSymbol != NULL && insertSymbols) + { + sprintf(buffer,"%s,%s",DisassemblyManager::getCpu()->GetRegName(0,rt),addressSymbol); + } else { + sprintf(buffer,"%s,0x%08X",DisassemblyManager::getCpu()->GetRegName(0,rt),immediate); + } + + dest.params = buffer; + + dest.info.hasRelevantAddress = true; + dest.info.releventAddress = immediate; + break; + case MACRO_MEMORYIMM: + dest.name = name; + + addressSymbol = symbolMap.GetLabelName(immediate); + if (addressSymbol != NULL && insertSymbols) + { + sprintf(buffer,"%s,%s",DisassemblyManager::getCpu()->GetRegName(0,rt),addressSymbol); + } else { + sprintf(buffer,"%s,0x%08X",DisassemblyManager::getCpu()->GetRegName(0,rt),immediate); + } + + dest.params = buffer; + + dest.info.isDataAccess = true; + dest.info.dataAddress = immediate; + dest.info.dataSize = dataSize; + + dest.info.hasRelevantAddress = true; + dest.info.releventAddress = immediate; + break; + default: + return false; + } + + dest.totalSize = getTotalSize(); + return true; +} + + +DisassemblyData::DisassemblyData(u32 _address, u32 _size, DataType _type): address(_address), size(_size), type(_type) +{ + hash = computeHash(address,size); + createLines(); +} + +void DisassemblyData::recheck() +{ + u32 newHash = computeHash(address,size); + if (newHash != hash) + { + hash = newHash; + createLines(); + } +} + +bool DisassemblyData::disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) +{ + dest.type = DISTYPE_DATA; + + switch (type) + { + case DATATYPE_BYTE: + dest.name = ".byte"; + break; + case DATATYPE_HALFWORD: + dest.name = ".half"; + break; + case DATATYPE_WORD: + dest.name = ".word"; + break; + case DATATYPE_ASCII: + dest.name = ".ascii"; + break; + default: + return false; + } + + auto it = lines.find(address); + if (it == lines.end()) + return false; + + dest.params = it->second.text; + dest.totalSize = it->second.size; + return true; +} + +int DisassemblyData::getLineNum(u32 address, bool findStart) +{ + auto it = lines.upper_bound(address); + if (it != lines.end()) + { + if (it == lines.begin()) + return 0; + it--; + return it->second.lineNum; + } + + return lines.rbegin()->second.lineNum; +} + +void DisassemblyData::createLines() +{ + lines.clear(); + lineAddresses.clear(); + + u32 pos = address; + u32 end = address+size; + u32 maxChars = DisassemblyManager::getMaxParamChars(); + + std::string currentLine; + u32 currentLineStart = pos; + + int lineCount = 0; + if (type == DATATYPE_ASCII) + { + bool inString = false; + while (pos < end) + { + u8 b = Memory::Read_U8(pos++); + if (b >= 0x20 && b <= 0x7F) + { + if (currentLine.size()+1 >= maxChars) + { + if (inString == true) + currentLine += "\""; + + DataEntry entry = {currentLine,pos-1-currentLineStart,lineCount++}; + lines[currentLineStart] = entry; + lineAddresses.push_back(currentLineStart); + + currentLine = ""; + currentLineStart = pos-1; + inString = false; + } + + if (inString == false) + currentLine += "\""; + currentLine += (char)b; + inString = true; + } else { + char buffer[64]; + if (pos == end && b == 0) + strcpy(buffer,"0"); + else + sprintf(buffer,"0x%02X",b); + + if (currentLine.size()+strlen(buffer) >= maxChars) + { + if (inString == true) + currentLine += "\""; + + DataEntry entry = {currentLine,pos-1-currentLineStart,lineCount++}; + lines[currentLineStart] = entry; + lineAddresses.push_back(currentLineStart); + + currentLine = ""; + currentLineStart = pos-1; + inString = false; + } + + bool comma = false; + if (currentLine.size() != 0) + comma = true; + + if (inString) + currentLine += "\""; + + if (comma) + currentLine += ","; + + currentLine += buffer; + inString = false; + } + } + + if (inString == true) + currentLine += "\""; + + if (currentLine.size() != 0) + { + DataEntry entry = {currentLine,pos-currentLineStart,lineCount++}; + lines[currentLineStart] = entry; + lineAddresses.push_back(currentLineStart); + } + } else { + while (pos < end) + { + char buffer[64]; + u32 value; + + u32 currentPos = pos; + + switch (type) + { + case DATATYPE_BYTE: + value = Memory::Read_U8(pos); + sprintf(buffer,"0x%02X",value); + pos++; + break; + case DATATYPE_HALFWORD: + value = Memory::Read_U16(pos); + sprintf(buffer,"0x%04X",value); + pos += 2; + break; + case DATATYPE_WORD: + { + value = Memory::Read_U32(pos); + const char* label = symbolMap.GetLabelName(value); + if (label != NULL) + sprintf(buffer,"%s",label); + else + sprintf(buffer,"0x%08X",value); + pos += 4; + } + break; + } + + size_t len = strlen(buffer); + if (currentLine.size() != 0 && currentLine.size()+len >= maxChars) + { + DataEntry entry = {currentLine,currentPos-currentLineStart,lineCount++}; + lines[currentLineStart] = entry; + lineAddresses.push_back(currentLineStart); + + currentLine = ""; + currentLineStart = currentPos; + } + + if (currentLine.size() != 0) + currentLine += ","; + currentLine += buffer; + } + + if (currentLine.size() != 0) + { + DataEntry entry = {currentLine,pos-currentLineStart,lineCount++}; + lines[currentLineStart] = entry; + lineAddresses.push_back(currentLineStart); + } + } +} + + +DisassemblyComment::DisassemblyComment(u32 _address, u32 _size, std::string _name, std::string _param) + : address(_address), size(_size), name(_name), param(_param) +{ + +} + +bool DisassemblyComment::disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) +{ + dest.type = DISTYPE_OTHER; + dest.name = name; + dest.params = param; + dest.totalSize = size; + return true; +} diff --git a/Core/Debugger/DisassemblyManager.h b/Core/Debugger/DisassemblyManager.h new file mode 100644 index 0000000000..ae1847dcdc --- /dev/null +++ b/Core/Debugger/DisassemblyManager.h @@ -0,0 +1,207 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once +#include "Globals.h" +#include "Core/MIPS/MIPSAnalyst.h" + +enum DisassemblyLineType { DISTYPE_OPCODE, DISTYPE_MACRO, DISTYPE_DATA, DISTYPE_OTHER }; + +struct DisassemblyLineInfo +{ + DisassemblyLineType type; + MIPSAnalyst::MipsOpcodeInfo info; + std::string name; + std::string params; + u32 totalSize; +}; + +enum LineType { LINE_UP, LINE_DOWN, LINE_RIGHT }; + +struct BranchLine +{ + u32 first; + u32 second; + LineType type; + int laneIndex; + + bool operator<(const BranchLine& other) const + { + return first < other.first; + } +}; + +class DisassemblyEntry +{ +public: + virtual ~DisassemblyEntry() { }; + virtual void recheck() = 0; + virtual int getNumLines() = 0; + virtual int getLineNum(u32 address, bool findStart) = 0; + virtual u32 getLineAddress(int line) = 0; + virtual u32 getTotalSize() = 0; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) = 0; + virtual void getBranchLines(u32 start, u32 size, std::vector& dest) { }; +}; + +class DisassemblyFunction: public DisassemblyEntry +{ +public: + DisassemblyFunction(u32 _address, u32 _size); + virtual void recheck(); + virtual int getNumLines(); + virtual int getLineNum(u32 address, bool findStart); + virtual u32 getLineAddress(int line); + virtual u32 getTotalSize() { return size; }; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols); + virtual void getBranchLines(u32 start, u32 size, std::vector& dest); +private: + void generateBranchLines(); + void load(); + void clear(); + void addOpcodeSequence(u32 start, u32 end); + + u32 address; + u32 size; + u32 hash; + std::vector lines; + std::map entries; + std::vector lineAddresses; +}; + +class DisassemblyOpcode: public DisassemblyEntry +{ +public: + DisassemblyOpcode(u32 _address, int _num): address(_address), num(_num) { }; + virtual ~DisassemblyOpcode() { }; + virtual void recheck() { }; + virtual int getNumLines() { return num; }; + virtual int getLineNum(u32 address, bool findStart) { return (address-this->address)/4; }; + virtual u32 getLineAddress(int line) { return address+line*4; }; + virtual u32 getTotalSize() { return num*4; }; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols); + virtual void getBranchLines(u32 start, u32 size, std::vector& dest); +private: + u32 address; + int num; +}; + + +class DisassemblyMacro: public DisassemblyEntry +{ +public: + DisassemblyMacro(u32 _address): address(_address) { }; + virtual ~DisassemblyMacro() { }; + + void setMacroLi(u32 _immediate, u8 _rt); + void setMacroMemory(std::string _name, u32 _immediate, u8 _rt, int _dataSize); + + virtual void recheck() { }; + virtual int getNumLines() { return 1; }; + virtual int getLineNum(u32 address, bool findStart) { return 0; }; + virtual u32 getLineAddress(int line) { return address; }; + virtual u32 getTotalSize() { return numOpcodes*4; }; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) ; +private: + enum MacroType { MACRO_LI, MACRO_MEMORYIMM }; + + MacroType type; + std::string name; + u32 immediate; + u32 address; + u32 numOpcodes; + u8 rt; + int dataSize; +}; + + +class DisassemblyData: public DisassemblyEntry +{ +public: + DisassemblyData(u32 _address, u32 _size, DataType _type); + virtual ~DisassemblyData() { }; + + virtual void recheck(); + virtual int getNumLines() { return (int)lines.size(); }; + virtual int getLineNum(u32 address, bool findStart); + virtual u32 getLineAddress(int line) { return lineAddresses[line]; }; + virtual u32 getTotalSize() { return size; }; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols); +private: + void createLines(); + + struct DataEntry + { + std::string text; + u32 size; + int lineNum; + }; + + u32 address; + u32 size; + u32 hash; + DataType type; + std::map lines; + std::vector lineAddresses; +}; + +class DisassemblyComment: public DisassemblyEntry +{ +public: + DisassemblyComment(u32 _address, u32 _size, std::string name, std::string param); + virtual ~DisassemblyComment() { }; + + virtual void recheck() { }; + virtual int getNumLines() { return 1; }; + virtual int getLineNum(u32 address, bool findStart) { return 0; }; + virtual u32 getLineAddress(int line) { return address; }; + virtual u32 getTotalSize() { return size; }; + virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols); +private: + u32 address; + u32 size; + std::string name; + std::string param; +}; + +class DebugInterface; + +class DisassemblyManager +{ +public: + void clear(); + + void setCpu(DebugInterface* _cpu) { cpu = _cpu; }; + void setMaxParamChars(int num) { maxParamChars = num; clear(); }; + void getLine(u32 address, bool insertSymbols, DisassemblyLineInfo& dest); + void analyze(u32 address, u32 size); + std::vector getBranchLines(u32 start, u32 size); + + u32 getStartAddress(u32 address); + u32 getNthPreviousAddress(u32 address, int n = 1); + u32 getNthNextAddress(u32 address, int n = 1); + + static DebugInterface* getCpu() { return cpu; }; + static int getMaxParamChars() { return maxParamChars; }; +private: + DisassemblyEntry* getEntry(u32 address); + static std::map entries; + static DebugInterface* cpu; + static int maxParamChars; +}; + +bool isInInterval(u32 start, u32 size, u32 value); \ No newline at end of file diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index 3c3c7940f7..1482cd4d22 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -31,109 +31,20 @@ SymbolMap symbolMap; -//need improvement -static u32 hasher(u32 last, u32 value) -{ - return __rotl(last,3) ^ value; -} - -//#define BWLINKS - -// TODO: This should ignore immediates of many instructions, in order to be less sensitive. If it did, -// this could work okay. -static u32 ComputeHash(u32 start, u32 size) -{ - u32 hash=0; - for (unsigned int i=start; i> 26) { - case 18: - { - if (LK) { - u32 addr; - if(AA) - addr = SignExt26(LI << 2); - else - addr = ptr + SignExt26(LI << 2); - - int funNum = GetSymbolNum(addr); - if (funNum >= 0) - entries[funNum].backwardLinks.push_back(ptr); - } - break; - } - default: - ; - } - - ptr += 4; - } - } -#endif + AssignFunctionIndices(); } void SymbolMap::Clear() { lock_guard guard(lock_); -#ifdef BWLINKS - for (int i=0; i 0; i--) { if (line[i] == '\r' || line[i] == '\n') { @@ -182,26 +92,41 @@ bool SymbolMap::LoadSymbolMap(const char *filename) if (temp[1]==']') continue; if (!started) continue; - MapEntry e; - memset(&e, 0, sizeof(e)); - sscanf(line,"%08x %08x %08x %i %127c",&e.address,&e.size,&e.vaddress,(int*)&e.type,e.name); - - if (e.type == ST_DATA && e.size==0) - e.size=4; - //e.vaddress|=0x80000000; - if (strcmp(e.name,".text")==0 || strcmp(e.name,".init")==0 || strlen(e.name)<=1) { - ; + u32 address, size, vaddress; + SymbolType type; + char name[128] = {0}; + + sscanf(line,"%08x %08x %08x %i %127c", &address, &size, &vaddress, (int*)&type, name); + if (!Memory::IsValidAddress(vaddress)) { + ERROR_LOG(LOADER, "Invalid address in symbol file: %08x (%s)", vaddress, name); + continue; + } + if (type == ST_DATA && size == 0) + size = 4; + + if (!strcmp(name, ".text") || !strcmp(name, ".init") || strlen(name) <= 1) { + } else { - e.UndecorateName(); - entries.push_back(e); - uniqueEntries.insert((const MapEntryUniqueInfo)e); - entryRanges[e.vaddress + e.size] = e.vaddress; + switch (type) + { + case ST_FUNCTION: + AddFunction(name, vaddress, size); + break; + case ST_DATA: + AddData(vaddress,size,DATATYPE_BYTE); + if (name[0] != 0) + AddLabel(name, vaddress); + break; + case ST_NONE: + case ST_ALL: + // Shouldn't be possible. + break; + } } } fclose(f); SortSymbols(); - // SymbolMap::AnalyzeBackwards(); return true; } @@ -213,10 +138,14 @@ void SymbolMap::SaveSymbolMap(const char *filename) const if (!f) return; fprintf(f,".text\n"); - for (auto it = entries.begin(), end = entries.end(); it != end; ++it) - { - const MapEntry &e = *it; - fprintf(f,"%08x %08x %08x %i %s\n",e.address,e.size,e.vaddress,e.type,e.name); + for (auto it = functions.begin(), end = functions.end(); it != end; ++it) { + const FunctionEntry& e = it->second; + fprintf(f,"%08x %08x %08x %i %s\n",it->first,e.size,it->first,ST_FUNCTION,GetLabelName(it->first)); + } + + for (auto it = data.begin(), end = data.end(); it != end; ++it) { + const DataEntry& e = it->second; + fprintf(f,"%08x %08x %08x %i %s\n",it->first,e.size,it->first,ST_DATA,GetLabelName(it->first)); } fclose(f); } @@ -228,29 +157,51 @@ bool SymbolMap::LoadNocashSym(const char *filename) if (!f) return false; - while (!feof(f)) - { + while (!feof(f)) { char line[256], value[256] = {0}; - char *p = fgets(line,256,f); - if(p == NULL) + char *p = fgets(line, 256, f); + if (p == NULL) break; u32 address; - if (sscanf(line,"%08X %s",&address,value) != 2) continue; - if (address == 0 && strcmp(value,"0") == 0) continue; + if (sscanf(line, "%08X %s", &address, value) != 2) + continue; + if (address == 0 && strcmp(value, "0") == 0) + continue; - if (value[0] == '.') // data directives - { - continue; // not supported yet + if (value[0] == '.') { + // data directives + char* s = strchr(value, ':'); + if (s != NULL) { + *s = 0; + + u32 size = 0; + if (sscanf(s + 1, "%04X", &size) != 1) + continue; + + if (strcasecmp(value, ".byt") == 0) { + AddData(address, size, DATATYPE_BYTE); + } else if (strcasecmp(value, ".wrd") == 0) { + AddData(address, size, DATATYPE_HALFWORD); + } else if (strcasecmp(value, ".dbl") == 0) { + AddData(address, size, DATATYPE_WORD); + } else if (strcasecmp(value, ".asc") == 0) { + AddData(address, size, DATATYPE_ASCII); + } + } } else { // labels int size = 1; char* seperator = strchr(value,','); - if (seperator != NULL) - { + if (seperator != NULL) { *seperator = 0; sscanf(seperator+1,"%08X",&size); } - AddSymbol(value,address,size,ST_FUNCTION); + + if (size != 1) { + AddFunction(value,address,size); + } else { + AddLabel(value,address); + } } } @@ -258,443 +209,389 @@ bool SymbolMap::LoadNocashSym(const char *filename) return true; } -int SymbolMap::GetSymbolNum(unsigned int address, SymbolType symmask) const -{ - lock_guard guard(lock_); - for (size_t i = 0, n = entries.size(); i < n; i++) - { - const MapEntry &entry = entries[i]; - unsigned int addr = entry.vaddress; - if (address >= addr) - { - if (address < addr + entry.size) - { - if (entries[i].type & symmask) - return (int) i; - else - return -1; - } - } - else - break; - } - return -1; +SymbolType SymbolMap::GetSymbolType(u32 address) const { + if (functions.find(address) != functions.end()) + return ST_FUNCTION; + if (data.find(address) != data.end()) + return ST_DATA; + return ST_NONE; } bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) const { - lock_guard guard(lock_); - // entryRanges is indexed by end. The first entry after address should contain address. - // Otherwise, we have no entry that contains it, unless things overlap (which they shouldn't.) - const auto containingEntry = entryRanges.upper_bound(address); - if (containingEntry == entryRanges.end()) + u32 functionAddress = INVALID_ADDRESS; + u32 dataAddress = INVALID_ADDRESS; + + if (symmask & ST_FUNCTION) + functionAddress = GetFunctionStart(address); + + if (symmask & ST_DATA) + dataAddress = GetDataStart(address); + + if (functionAddress == INVALID_ADDRESS || dataAddress == INVALID_ADDRESS) + { + if (functionAddress != INVALID_ADDRESS) + { + if (info != NULL) + { + info->type = ST_FUNCTION; + info->address = functionAddress; + info->size = GetFunctionSize(functionAddress); + } + + return true; + } + + if (dataAddress != INVALID_ADDRESS) + { + if (info != NULL) + { + info->type = ST_DATA; + info->address = dataAddress; + info->size = GetDataSize(dataAddress); + } + + return true; + } + return false; - - // The next most common case is a single symbol by start address. - // So we optimize for that by looking in our uniqueEntry set. - u32 start_address = containingEntry->second; - if (start_address <= address) - { - const MapEntryUniqueInfo searchKey = {start_address, start_address}; - const auto entry = uniqueEntries.find(searchKey); - // In case there were duplicates at some point, double check the end address. - if (entry != uniqueEntries.end() && entry->vaddress + entry->size > address && (entry->type & symmask) != 0) - { - info->address = entry->vaddress; - info->size = entry->size; - return true; - } } - // Fall back to a slower scan. - int n = GetSymbolNum(address, symmask); - if (n != -1) - { - info->address = GetSymbolAddr(n); - info->size = GetSymbolSize(n); - return true; + // if both exist, return the function + if (info != NULL) { + info->type = ST_FUNCTION; + info->address = functionAddress; + info->size = GetFunctionSize(functionAddress); } - return false; + return true; } -const char* SymbolMap::getDirectSymbol(u32 address) -{ - lock_guard guard(lock_); - SymbolInfo info; - if (GetSymbolInfo(&info,address) == false) return NULL; - if (info.address != address) return NULL; // has to be the START of the function +u32 SymbolMap::GetNextSymbolAddress(u32 address, SymbolType symmask) { + const auto functionEntry = symmask & ST_FUNCTION ? functions.upper_bound(address) : functions.end(); + const auto dataEntry = symmask & ST_DATA ? data.upper_bound(address) : data.end(); - // now we need the name... which we can't just get from GetSymbolInfo because of the - // unique entries. But, there are so many less instances where there actually IS a - // label that the speed up is still massive - for (auto it = entries.begin(), end = entries.end(); it != end; ++it) - { - const MapEntry &entry = *it; - unsigned int addr = entry.vaddress; - if (addr == address) return entry.name; - } - return NULL; -} + if (functionEntry == functions.end() && dataEntry == data.end()) + return INVALID_ADDRESS; -bool SymbolMap::getSymbolValue(char* symbol, u32& dest) -{ - lock_guard guard(lock_); - for (auto it = entries.begin(), end = entries.end(); it != end; ++it) - { - const MapEntry &entry = *it; -#ifdef _WIN32 - if (_stricmp(entry.name,symbol) == 0) -#else - if (strcasecmp(entry.name,symbol) == 0) -#endif - { - dest = entry.vaddress; - return true; - } - } - return false; + u32 funcAddress = (functionEntry != functions.end()) ? functionEntry->first : 0xFFFFFFFF; + u32 dataAddress = (dataEntry != data.end()) ? dataEntry->first : 0xFFFFFFFF; + + if (funcAddress <= dataAddress) + return funcAddress; + else + return dataAddress; } static char descriptionTemp[256]; -const char *SymbolMap::GetDescription(unsigned int address) const -{ - int fun = SymbolMap::GetSymbolNum(address); - //if (address == entries[fun].vaddress) - //{ - if (fun!=-1) - return entries[fun].name; - else - { - sprintf(descriptionTemp, "(%08x)", address); - return descriptionTemp; +const char *SymbolMap::GetDescription(unsigned int address) const { + const char* labelName = NULL; + + u32 funcStart = GetFunctionStart(address); + if (funcStart != INVALID_ADDRESS) { + labelName = GetLabelName(funcStart); + } else { + u32 dataStart = GetDataStart(address); + if (dataStart != INVALID_ADDRESS) + labelName = GetLabelName(dataStart); } - //} - //else - // return ""; + + if (labelName != NULL) + return labelName; + + sprintf(descriptionTemp, "(%08x)", address); + return descriptionTemp; +} + +std::vector SymbolMap::GetAllSymbols(SymbolType symmask) { + std::vector result; + + if (symmask & ST_FUNCTION) { + for (auto it = functions.begin(); it != functions.end(); it++) { + SymbolEntry entry; + entry.address = it->first; + entry.size = GetFunctionSize(entry.address); + const char* name = GetLabelName(entry.address); + if (name != NULL) + entry.name = name; + result.push_back(entry); + } + } + + if (symmask & ST_DATA) { + for (auto it = data.begin(); it != data.end(); it++) { + SymbolEntry entry; + entry.address = it->first; + entry.size = GetDataSize(entry.address); + const char* name = GetLabelName(entry.address); + if (name != NULL) + entry.name = name; + result.push_back(entry); + } + } + + return result; +} + +void SymbolMap::AddFunction(const char* name, u32 address, u32 size) { + lock_guard guard(lock_); + + FunctionEntry func; + func.size = size; + func.index = (int)functions.size(); + functions[address] = func; + + if (GetLabelName(address) == NULL) + AddLabel(name,address); +} + +u32 SymbolMap::GetFunctionStart(u32 address) const { + auto it = functions.upper_bound(address); + if (it == functions.end()) { + // check last element + auto rit = functions.rbegin(); + if (rit != functions.rend()) { + u32 start = rit->first; + u32 size = rit->second.size; + if (start <= address && start+size > address) + return start; + } + // otherwise there's no function that contains this address + return INVALID_ADDRESS; + } + + if (it != functions.begin()) { + it--; + u32 start = it->first; + u32 size = it->second.size; + if (start <= address && start+size > address) + return start; + } + + return INVALID_ADDRESS; +} + +u32 SymbolMap::GetFunctionSize(u32 startAddress) const { + auto it = functions.find(startAddress); + if (it == functions.end()) + return INVALID_ADDRESS; + + return it->second.size; +} + +int SymbolMap::GetFunctionNum(u32 address) const { + u32 start = GetFunctionStart(address); + if (start == INVALID_ADDRESS) + return INVALID_ADDRESS; + + auto it = functions.find(start); + if (it == functions.end()) + return INVALID_ADDRESS; + + return it->second.index; +} + +void SymbolMap::AssignFunctionIndices() { + int index = 0; + for (auto it = functions.begin(); it != functions.end(); it++) { + it->second.index = index++; + } +} + +bool SymbolMap::SetFunctionSize(u32 startAddress, u32 newSize) { + lock_guard guard(lock_); + + auto it = functions.find(startAddress); + if (it == functions.end()) + return false; + + it->second.size = newSize; + + // TODO: check for overlaps + return true; +} + +bool SymbolMap::RemoveFunction(u32 startAddress, bool removeName) { + lock_guard guard(lock_); + + auto it = functions.find(startAddress); + if (it == functions.end()) + return false; + + functions.erase(it); + if (removeName) { + auto labelIt = labels.find(startAddress); + if (labelIt != labels.end()) + labels.erase(labelIt); + } + + return true; +} + +void SymbolMap::AddLabel(const char* name, u32 address) { + // keep a label if it already exists + auto it = labels.find(address); + if (it == labels.end()) { + LabelEntry label; + strncpy(label.name, name, 128); + label.name[127] = 0; + labels[address] = label; + } +} + +void SymbolMap::SetLabelName(const char* name, u32 address) { + auto it = labels.find(address); + if (it == labels.end()) { + LabelEntry label; + strcpy(label.name,name); + label.name[127] = 0; + + labels[address] = label; + } else { + strcpy(it->second.name,name); + it->second.name[127] = 0; + } +} + +const char* SymbolMap::GetLabelName(u32 address) const { + auto it = labels.find(address); + if (it == labels.end()) + return NULL; + + return it->second.name; +} + +bool SymbolMap::GetLabelValue(const char* name, u32& dest) { + for (auto it = labels.begin(); it != labels.end(); it++) { + if (strcasecmp(name,it->second.name) == 0) { + dest = it->first; + return true; + } + } + + return false; +} + +void SymbolMap::AddData(u32 address, u32 size, DataType type) { + DataEntry entry; + entry.size = size; + entry.type = type; + data[address] = entry; +} + +u32 SymbolMap::GetDataStart(u32 address) const { + auto it = data.upper_bound(address); + if (it == data.end()) + { + // check last element + auto rit = data.rbegin(); + + if (rit != data.rend()) + { + u32 start = rit->first; + u32 size = rit->second.size; + if (start <= address && start+size > address) + return start; + } + // otherwise there's no data that contains this address + return INVALID_ADDRESS; + } + + if (it != data.begin()) { + it--; + u32 start = it->first; + u32 size = it->second.size; + if (start <= address && start+size > address) + return start; + } + + return INVALID_ADDRESS; +} + +u32 SymbolMap::GetDataSize(u32 startAddress) const { + auto it = data.find(startAddress); + if (it == data.end()) + return INVALID_ADDRESS; + return it->second.size; +} + +DataType SymbolMap::GetDataType(u32 startAddress) const { + auto it = data.find(startAddress); + if (it == data.end()) + return DATATYPE_NONE; + return it->second.type; } #ifdef _WIN32 -static const int defaultSymbolsAddresses[] = { - 0x08800000, 0x08804000, 0x04000000, 0x88000000, 0x00010000 +struct DefaultSymbol { + u32 address; + const char* name; }; -static const char* defaultSymbolsNames[] = { - "User memory", "Default load address", "VRAM","Kernel memory","Scratchpad" +static const DefaultSymbol defaultSymbols[]= { + { 0x08800000, "User memory" }, + { 0x08804000, "Default load address" }, + { 0x04000000, "VRAM" }, + { 0x88000000, "Kernel memory" }, + { 0x00010000, "Scratchpad" }, }; -static const int defaultSymbolsAmount = sizeof(defaultSymbolsAddresses)/sizeof(const int); - -void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symmask) const -{ - BOOL visible = ShowWindow(listbox,SW_HIDE); - ListBox_ResetContent(listbox); - - if (symmask & ST_DATA) - { - for (int i = 0; i < defaultSymbolsAmount; i++) - { - wchar_t temp[256]; - wsprintf(temp, L"0x%08X (%S)", defaultSymbolsAddresses[i], defaultSymbolsNames[i]); - int index = ListBox_AddString(listbox,temp); - ListBox_SetItemData(listbox,index,defaultSymbolsAddresses[i]); - } - } - +void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symType) const { + wchar_t temp[256]; lock_guard guard(lock_); SendMessage(listbox, WM_SETREDRAW, FALSE, 0); - SendMessage(listbox, LB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30); - for (auto it = entries.begin(), end = entries.end(); it != end; ++it) - { - const MapEntry &entry = *it; - if (entry.type & symmask) - { - wchar_t temp[256]; - if (entry.type & ST_FUNCTION || !(entry.type & ST_DATA)) - { - wsprintf(temp, L"%S", entry.name); - } else { - wsprintf(temp, L"0x%08X (%S)", entry.vaddress, entry.name); - } - - int index = ListBox_AddString(listbox,temp); - ListBox_SetItemData(listbox,index,entry.vaddress); - } - } - SendMessage(listbox, WM_SETREDRAW, TRUE, 0); - RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - - if (visible) - ShowWindow(listbox,SW_SHOW); -} - -void SymbolMap::FillSymbolComboBox(HWND listbox,SymbolType symmask) const -{ - ShowWindow(listbox,SW_HIDE); - ComboBox_ResetContent(listbox); - - //int style = GetWindowLong(listbox,GWL_STYLE); - - ComboBox_AddString(listbox, L"(0x02000000)"); - ComboBox_SetItemData(listbox, 0, 0x02000000); - - //ListBox_AddString(listbox, L"(0x80002000)"); - //ListBox_SetItemData(listbox, 1, 0x80002000); - - lock_guard guard(lock_); - - SendMessage(listbox, WM_SETREDRAW, FALSE, 0); - SendMessage(listbox, CB_INITSTORAGE, (WPARAM)entries.size(), (LPARAM)entries.size() * 30 * sizeof(wchar_t)); - for (size_t i = 0, end = entries.size(); i < end; ++i) - { - const MapEntry &entry = entries[i]; - if (entry.type & symmask) - { - wchar_t temp[256]; - wsprintf(temp, L"%S (%d)", entry.name, entry.size); - int index = ComboBox_AddString(listbox,temp); - ComboBox_SetItemData(listbox,index,entry.vaddress); - } - } - SendMessage(listbox, WM_SETREDRAW, TRUE, 0); - RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - ShowWindow(listbox,SW_SHOW); -} - -void SymbolMap::FillListBoxBLinks(HWND listbox, int num) const -{ ListBox_ResetContent(listbox); - lock_guard guard(lock_); - - int style = GetWindowLong(listbox,GWL_STYLE); - - const MapEntry &e = entries[num]; -#ifdef BWLINKS - for (int i=0; i::iterator it = uniqueEntries.find((const MapEntryUniqueInfo) e); - if (it != uniqueEntries.end()){ - MapEntryUniqueInfo temp = *it; - temp.size = newSize; - uniqueEntries.erase(it); - uniqueEntries.insert(temp); - } - entryRanges.erase(e.vaddress + e.size); - entryRanges.insert(std::pair(e.vaddress+newSize,e.vaddress)); - - e.size = newSize; -} - -u32 SymbolMap::GetSymbolAddr(int i) const -{ - return entries[i].vaddress; -} - -u32 SymbolMap::GetSymbolSize(int i) const -{ - return entries[i].size; -} - -int SymbolMap::FindSymbol(const char *name) const -{ - lock_guard guard(lock_); - for (size_t i = 0; i < entries.size(); i++) - if (strcmp(entries[i].name,name)==0) - return (int) i; - return -1; -} - -u32 SymbolMap::GetAddress(int num) const -{ - return entries[num].vaddress; -} - -void SymbolMap::IncreaseRunCount(int num) -{ - entries[num].runCount++; -} - -unsigned int SymbolMap::GetRunCount(int num) const -{ - if (num>=0) - return entries[num].runCount; - else - return 0; -} - -// Load an elf with symbols, use SymbolMap::compilefuncsignaturesfile -// to make a symbol map, load a dol or somethin without symbols, then apply -// the map with SymbolMap::usefuncsignaturesfile. - -void SymbolMap::CompileFuncSignaturesFile(const char *filename) const -{ - // Store name,length,first instruction,hash into file - FILE *f = File::OpenCFile(filename, "w"); - fprintf(f,"00000000\n"); - int count=0; - for (auto it = entries.begin(), end = entries.end(); it != end; ++it) - { - const MapEntry &entry = *it; - int size = entry.size; - if (size >= 16 && entry.type == ST_FUNCTION) + switch (symType) { + case ST_FUNCTION: { - u32 inst = Memory::Read_Instruction(entry.vaddress).encoding; //try to make a bigger number of different vals sometime - if (inst != 0) - { - char temp[64]; - strncpy(temp,entry.name,63); - fprintf(f, "%08x\t%08x\t%08x\t%s\n", inst, size, ComputeHash(entry.vaddress,size), temp); - count++; + SendMessage(listbox, LB_INITSTORAGE, (WPARAM)functions.size(), (LPARAM)functions.size() * 30); + + for (auto it = functions.begin(), end = functions.end(); it != end; ++it) { + const FunctionEntry& entry = it->second; + const char* name = GetLabelName(it->first); + if (name != NULL) + wsprintf(temp, L"%S", name); + else + wsprintf(temp, L"0x%08X", it->first); + int index = ListBox_AddString(listbox,temp); + ListBox_SetItemData(listbox,index,it->first); } } - } - fseek(f,0,SEEK_SET); - fprintf(f,"%08x",count); - fclose(f); -} + break; - -struct Sig -{ - u32 inst; - u32 size; - u32 hash; - char name[64]; - Sig(){} - Sig(u32 _inst, u32 _size, u32 _hash, char *_name) : inst(_inst), size(_size), hash(_hash) - { - strncpy(name,_name,63); - } - bool operator <(const Sig &other) const { - return inst < other.inst; - } -}; - -std::vector sigs; - -typedef std::map Sigmap; -Sigmap sigmap; - -void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) -{ - sigs.clear(); - // symbolMap.Clear(); - //#1: Read the signature file and put them in a fast data structure - FILE *f = File::OpenCFile(filename, "r"); - int count; - if (fscanf(f, "%08x\n", &count) != 1) - count = 0; - char name[256]; - for (int a=0; asecond; - while (true) - { - if (sig->inst != inst) - break; + for (auto it = data.begin(), end = data.end(); it != end; ++it) { + const DataEntry& entry = it->second; + const char* name = GetLabelName(it->first); - u32 hash = ComputeHash(addr,sig->size); - if (hash==sig->hash) - { - //MATCH!!!! - MapEntry e; - e.address=addr; - e.size= sig->size; - e.vaddress = addr; - e.type=ST_FUNCTION; - strcpy(e.name,sig->name); - addr+=sig->size-4; //don't need to check function interior - entries.push_back(e); - uniqueEntries.insert((const MapEntryUniqueInfo)e); - entryRanges[e.vaddress + e.size] = e.vaddress; - break; - } - sig++; + if (name != NULL) + wsprintf(temp, L"%S", name); + else + wsprintf(temp, L"0x%08X", it->first); + + int index = ListBox_AddString(listbox,temp); + ListBox_SetItemData(listbox,index,it->first); } } + break; } - //ensure code coloring even if symbols were loaded before - SymbolMap::SortSymbols(); + + SendMessage(listbox, WM_SETREDRAW, TRUE, 0); + RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); } + +#endif diff --git a/Core/Debugger/SymbolMap.h b/Core/Debugger/SymbolMap.h index 97263a9112..284eb5d006 100644 --- a/Core/Debugger/SymbolMap.h +++ b/Core/Debugger/SymbolMap.h @@ -24,15 +24,28 @@ #include enum SymbolType { - ST_FUNCTION=1, - ST_DATA=2 + ST_NONE = 0, + ST_FUNCTION = 1, + ST_DATA = 2, + ST_ALL = 3, }; struct SymbolInfo { + SymbolType type; u32 address; u32 size; }; +struct SymbolEntry { + std::string name; + u32 address; + u32 size; +}; + +enum DataType { + DATATYPE_NONE, DATATYPE_BYTE, DATATYPE_HALFWORD, DATATYPE_WORD, DATATYPE_ASCII +}; + #ifdef _WIN32 struct HWND__; typedef struct HWND__ *HWND; @@ -41,68 +54,64 @@ typedef struct HWND__ *HWND; class SymbolMap { public: SymbolMap() {} + void Clear(); + void SortSymbols(); + bool LoadSymbolMap(const char *filename); void SaveSymbolMap(const char *filename) const; bool LoadNocashSym(const char *ilename); - void AddSymbol(const char *symbolname, unsigned int vaddress, size_t size, SymbolType symbol); - void RemoveSymbolNum(int symbolnum); - void Clear(); - void AnalyzeBackwards(); - int GetSymbolNum(unsigned int address, SymbolType symmask=ST_FUNCTION) const; + + SymbolType GetSymbolType(u32 address) const; bool GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask = ST_FUNCTION) const; + u32 GetNextSymbolAddress(u32 address, SymbolType symmask); const char *GetDescription(unsigned int address) const; + std::vector GetAllSymbols(SymbolType symmask); + #ifdef _WIN32 - void FillSymbolListBox(HWND listbox, SymbolType symmask=ST_FUNCTION) const; - void FillSymbolComboBox(HWND listbox,SymbolType symmask=ST_FUNCTION) const; - void FillListBoxBLinks(HWND listbox, int num) const; + void FillSymbolListBox(HWND listbox, SymbolType symType) const; #endif - int GetNumSymbols() const; - const char *GetSymbolName(int i) const; - void SetSymbolName(int i, const char *newname); - void SetSymbolSize(int i, int newSize); - u32 GetSymbolSize(int i) const; - u32 GetSymbolAddr(int i) const; - SymbolType GetSymbolType(int i) const; - int FindSymbol(const char *name) const; - u32 GetAddress(int num) const; - void IncreaseRunCount(int num); - unsigned int GetRunCount(int num) const; - void SortSymbols(); - const char* getDirectSymbol(u32 address); - bool getSymbolValue(char* symbol, u32& dest); - void UseFuncSignaturesFile(const char *filename, u32 maxAddress); - void CompileFuncSignaturesFile(const char *filename) const; + void AddFunction(const char* name, u32 address, u32 size); + u32 GetFunctionStart(u32 address) const; + int GetFunctionNum(u32 address) const; + u32 GetFunctionSize(u32 startAddress) const; + bool SetFunctionSize(u32 startAddress, u32 newSize); + bool RemoveFunction(u32 startAddress, bool removeName); + void AddLabel(const char* name, u32 address); + void SetLabelName(const char* name, u32 address); + const char* GetLabelName(u32 address) const; + bool GetLabelValue(const char* name, u32& dest); + + void AddData(u32 address, u32 size, DataType type); + u32 GetDataStart(u32 address) const; + u32 GetDataSize(u32 startAddress) const; + DataType GetDataType(u32 startAddress) const; + + static const u32 INVALID_ADDRESS = (u32)-1; private: - struct MapEntryUniqueInfo { - u32 address; - u32 vaddress; + void AssignFunctionIndices(); + + struct FunctionEntry { u32 size; - SymbolType type; - - bool operator < (const MapEntryUniqueInfo &other) const { - return vaddress < other.vaddress; - } + int index; }; - struct MapEntry : public MapEntryUniqueInfo { + struct LabelEntry { char name[128]; - u32 unknown; - u32 runCount; - -#ifdef BWLINKS - std::vector backwardLinks; -#endif - void UndecorateName() { - // TODO - } }; - std::set uniqueEntries; - std::vector entries; - std::map entryRanges; + struct DataEntry { + DataType type; + u32 size; + }; + + std::map functions; + std::map labels; + std::map data; + mutable recursive_mutex lock_; }; extern SymbolMap symbolMap; + diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 3212bab0a2..c0498f95b0 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -128,6 +128,25 @@ bool PSPDialog::IsButtonPressed(int checkButton) return !isFading && !(lastButtons & checkButton) && (buttons & checkButton); } +bool PSPDialog::IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold, int framesHeldRepeatRate) +{ + bool btnWasHeldLastFrame = (lastButtons & checkButton) && (buttons & checkButton); + if (!isFading && btnWasHeldLastFrame) { + framesHeld++; + } + else { + framesHeld = 0; + return false; + } + + // It's considered held for dialog purposes after 30 frames (~0.5 seconds), + // and set to repeat every 10 frames, by default. + if (framesHeld >= framesHeldThreshold && ((framesHeld % framesHeldRepeatRate) == 0)) + return true; + + return false; +} + void PSPDialog::DisplayButtons(int flags) { I18NCategory *d = GetI18NCategory("Dialog"); diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index 465cec3b9d..30d13f96c2 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -79,6 +79,7 @@ public: void EndDraw(); protected: bool IsButtonPressed(int checkButton); + bool IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold = 30, int framesHeldRepeatRate = 10); void DisplayButtons(int flags); void StartFade(bool fadeIn_); diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 63e6ce065e..0b8e4c9e06 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -147,7 +147,10 @@ void PSPGamedataInstallDialog::updateProgress() { // Update progress bar(if there is). // progress value is progress[3] << 24 | progress[2] << 16 | progress[1] << 8 | progress[0]. // We only should update progress[0] here as the max progress value is 100. - progressValue = (int)(allReadSize / allFilesSize) * 100; + if (allFilesSize != 0) + progressValue = (int)(allReadSize / allFilesSize) * 100; + else + progressValue = 100; request.progress[0] = progressValue; Memory::WriteStruct(paramAddr,&request); } diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index d047c75cd1..31775cefa0 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -18,6 +18,11 @@ #include "PSPNetconfDialog.h" #include "ChunkFile.h" #include "../Core/MemMap.h" +#include "../Core/HLE/sceNetAdhoc.h" + +#define NETCONF_CONNECT_ADHOC 2 +#define NETCONF_CREATE_ADHOC 4 +#define NETCONF_JOIN_ADHOC 5 PSPNetconfDialog::PSPNetconfDialog() { } @@ -40,6 +45,19 @@ int PSPNetconfDialog::Init(u32 paramAddr) { } int PSPNetconfDialog::Update(int animSpeed) { + if(request.netAction == NETCONF_CONNECT_ADHOC || + request.netAction == NETCONF_CREATE_ADHOC || + request.netAction == NETCONF_JOIN_ADHOC){ + if(request.NetconfData != NULL){ + Shutdown(true); + if(sceNetAdhocctlCreate(request.NetconfData->groupName) == 0) + { + status = SCE_UTILITY_STATUS_FINISHED; + return 0; + } + return -1; + } + } return 0; } @@ -58,4 +76,4 @@ void PSPNetconfDialog::DoState(PointerWrap &p) { return; p.Do(request); -} \ No newline at end of file +} diff --git a/Core/Dialog/PSPNetconfDialog.h b/Core/Dialog/PSPNetconfDialog.h index 421e41ac69..9774e74891 100644 --- a/Core/Dialog/PSPNetconfDialog.h +++ b/Core/Dialog/PSPNetconfDialog.h @@ -46,4 +46,4 @@ public: private: SceUtilityNetconfParam request; -}; \ No newline at end of file +}; diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 46fb8b0a9b..3405a53371 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -17,6 +17,7 @@ #include "i18n/i18n.h" #include "math/math_util.h" +#include #include "Core/Dialog/PSPOskDialog.h" #include "Core/Util/PPGeDraw.h" @@ -27,8 +28,8 @@ #include "Common/ChunkFile.h" #include "GPU/GPUState.h" -#ifdef _WIN32 -#include "Core/Host.h" +#if defined(_WIN32) && !defined(USING_QT_UI) +#include "base/NativeApp.h" #endif #ifndef _WIN32 @@ -705,12 +706,14 @@ void PSPOskDialog::RenderKeyboard() std::string buffer; + u32 FIELDDRAWMAX = 15; u32 limit = FieldMaxLength(); + u32 drawLimit = std::min(FIELDDRAWMAX, limit); // Field drew length limit. const float keyboardLeftSide = (480.0f - (24.0f * numKeyCols[currentKeyboard])) / 2.0f; const float characterWidth = 12.0f; - float previewLeftSide = (480.0f - (12.0f * limit)) / 2.0f; - float title = (480.0f - (0.5f * limit)) / 2.0f; + float previewLeftSide = (480.0f - (12.0f * drawLimit)) / 2.0f; + float title = (480.0f - (0.5f * drawLimit)) / 2.0f; PPGeDrawText(oskDesc.c_str(), title , 20, PPGE_ALIGN_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF)); @@ -719,20 +722,22 @@ void PSPOskDialog::RenderKeyboard() result = CombinationString(false); - for (u32 i = 0; i < limit; ++i) + u32 drawIndex = (u32)(result.size() > drawLimit ? result.size() - drawLimit : 0); + drawIndex = result.size() == limit + 1 ? drawIndex - 1 : drawIndex; // When the length reached limit, the last character don't fade in and out. + for (u32 i = 0; i < drawLimit; ++i, ++drawIndex) { u32 color = CalcFadedColor(0xFFFFFFFF); - if (i + 1 < result.size()) + if (drawIndex + 1 < result.size()) { - temp[0] = result[i]; + temp[0] = result[drawIndex]; ConvertUCS2ToUTF8(buffer, temp); PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, PPGE_ALIGN_HCENTER, 0.5f, color); } else { - if (i + 1 == result.size()) + if (drawIndex + 1 == result.size()) { - temp[0] = result[i]; + temp[0] = result[drawIndex]; if(isCombinated == true) { @@ -781,7 +786,7 @@ void PSPOskDialog::RenderKeyboard() } } -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) // TODO: Why does this have a 2 button press lag/delay when // re-opening the dialog box? I don't get it. int PSPOskDialog::NativeKeyboard() @@ -803,7 +808,7 @@ int PSPOskDialog::NativeKeyboard() if(defaultText.empty()) defaultText.assign(L"VALUE"); - if(host->InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) + if(System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) { u32 maxLength = FieldMaxLength(); if (inputChars.length() > maxLength) @@ -844,15 +849,26 @@ int PSPOskDialog::NativeKeyboard() int PSPOskDialog::Update(int animSpeed) { - buttons = __CtrlReadLatch(); + int cancelButton = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS; + int confirmButton = cancelButton == CTRL_CROSS ? CTRL_CIRCLE : CTRL_CROSS; + static int cancelBtnFramesHeld = 0; + static int confirmBtnFramesHeld = 0; + static int leftBtnFramesHeld = 0; + static int upBtnFramesHeld = 0; + static int downBtnFramesHeld = 0; + static int rightBtnFramesHeld = 0; + const int framesHeldThreshold = 10; + const int framesHeldRepeatRate = 5; + + buttons = __CtrlPeekButtons(); int selectedRow = selectedChar / numKeyCols[currentKeyboard]; int selectedExtra = selectedChar % numKeyCols[currentKeyboard]; // TODO: Add your platforms here when you have a NativeKeyboard func. -#ifdef _WIN32 - // Fall back to the OSK/continue normally if we're in fullscreen. The dialog box - // doesn't work right if in fullscreen. +#if defined(_WIN32) && !defined(USING_QT_UI) + // Windows: Fall back to the OSK/continue normally if we're in fullscreen. + // The dialog box doesn't work right if in fullscreen. if(g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen) return NativeKeyboard(); #endif @@ -920,21 +936,21 @@ int PSPOskDialog::Update(int animSpeed) PPGeDrawText("R", 300, 245, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(language, 315, 247, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); - if (IsButtonPressed(CTRL_UP)) + if (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { selectedChar -= numKeyCols[currentKeyboard]; } - else if (IsButtonPressed(CTRL_DOWN)) + else if (IsButtonPressed(CTRL_DOWN) || IsButtonHeld(CTRL_DOWN, downBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { selectedChar += numKeyCols[currentKeyboard]; } - else if (IsButtonPressed(CTRL_LEFT)) + else if (IsButtonPressed(CTRL_LEFT) || IsButtonHeld(CTRL_LEFT, leftBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { selectedChar--; if (((selectedChar + numKeyCols[currentKeyboard]) % numKeyCols[currentKeyboard]) == numKeyCols[currentKeyboard] - 1) selectedChar += numKeyCols[currentKeyboard]; } - else if (IsButtonPressed(CTRL_RIGHT)) + else if (IsButtonPressed(CTRL_RIGHT) || IsButtonHeld(CTRL_RIGHT, rightBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { selectedChar++; if ((selectedChar % numKeyCols[currentKeyboard]) == 0) @@ -943,7 +959,7 @@ int PSPOskDialog::Update(int animSpeed) selectedChar = (selectedChar + (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard])) % (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard]); - if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CROSS : CTRL_CIRCLE)) + if (IsButtonPressed(confirmButton) || IsButtonHeld(confirmButton, confirmBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { inputChars = CombinationString(true); } @@ -1009,7 +1025,7 @@ int PSPOskDialog::Update(int animSpeed) selectedChar = selectedRow * numKeyCols[currentKeyboard] + selectedExtra; } - else if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CIRCLE : CTRL_CROSS)) + else if (IsButtonPressed(cancelButton) || IsButtonHeld(cancelButton, cancelBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { if (inputChars.size() > 0) { @@ -1046,7 +1062,7 @@ int PSPOskDialog::Update(int animSpeed) oskParams->base.result = 0; oskParams->fields[0].result = PSP_UTILITY_OSK_RESULT_CHANGED; - + lastButtons = buttons; return 0; } diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h index eeefc41369..a22cbfbc7f 100644 --- a/Core/Dialog/PSPOskDialog.h +++ b/Core/Dialog/PSPOskDialog.h @@ -215,7 +215,7 @@ private: void ConvertUCS2ToUTF8(std::string& _string, const PSPPointer em_address); void ConvertUCS2ToUTF8(std::string& _string, const wchar_t *input); void RenderKeyboard(); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) int NativeKeyboard(); #endif diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 969e14b68b..4612b99c71 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -61,8 +61,7 @@ int PSPSaveDialog::Init(int paramAddr) switch ((SceUtilitySavedataFocus)(u32)param.GetPspParam()->focus) { case SCE_UTILITY_SAVEDATA_FOCUS_NAME: - // TODO: This should probably force not using the list? - currentSelectedSave = 0; + currentSelectedSave = param.GetSaveNameIndex(param.GetPspParam()); break; case SCE_UTILITY_SAVEDATA_FOCUS_FIRSTLIST: currentSelectedSave = param.GetFirstListSave(); @@ -270,11 +269,15 @@ void PSPSaveDialog::DisplayBanner(int which) void PSPSaveDialog::DisplaySaveList(bool canMove) { int displayCount = 0; + static int upFramesHeld = 0; + static int downFramesHeld = 0; + for (int i = 0; i < param.GetFilenameCount(); i++) { int textureColor = 0xFFFFFFFF; + auto fileInfo = param.GetFileInfo(i); - if (param.GetFileInfo(i).size == 0 && param.GetFileInfo(i).textureData == 0) + if (fileInfo.size == 0 && fileInfo.texture != NULL) textureColor = 0xFF777777; // Calc save image position on screen @@ -301,21 +304,21 @@ void PSPSaveDialog::DisplaySaveList(bool canMove) int tw = 256; int th = 256; - if (param.GetFileInfo(i).textureData != 0) { - tw = param.GetFileInfo(i).textureWidth; - th = param.GetFileInfo(i).textureHeight; - PPGeSetTexture(param.GetFileInfo(i).textureData, param.GetFileInfo(i).textureWidth, param.GetFileInfo(i).textureHeight); + if (fileInfo.texture != NULL) { + fileInfo.texture->SetTexture(); + tw = fileInfo.texture->Width(); + th = fileInfo.texture->Height(); PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor); - } else - PPGeDisableTexture(); + } PPGeSetDefaultTexture(); displayCount++; } if (canMove) { - if (IsButtonPressed(CTRL_UP) && currentSelectedSave > 0) + if ( (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upFramesHeld)) && currentSelectedSave > 0) currentSelectedSave--; - else if (IsButtonPressed(CTRL_DOWN) && currentSelectedSave < (param.GetFilenameCount()-1)) + + else if ( (IsButtonPressed(CTRL_DOWN) || IsButtonHeld(CTRL_DOWN, downFramesHeld)) && currentSelectedSave < (param.GetFilenameCount() - 1)) currentSelectedSave++; } } @@ -323,8 +326,9 @@ void PSPSaveDialog::DisplaySaveList(bool canMove) void PSPSaveDialog::DisplaySaveIcon() { int textureColor = CalcFadedColor(0xFFFFFFFF); + auto curSave = param.GetFileInfo(currentSelectedSave); - if (param.GetFileInfo(currentSelectedSave).size == 0) + if (curSave.size == 0) textureColor = CalcFadedColor(0xFF777777); // Calc save image position on screen @@ -335,14 +339,15 @@ void PSPSaveDialog::DisplaySaveIcon() int tw = 256; int th = 256; - if (param.GetFileInfo(currentSelectedSave).textureData != 0) { - tw = param.GetFileInfo(currentSelectedSave).textureWidth; - th = param.GetFileInfo(currentSelectedSave).textureHeight; - PPGeSetTexture(param.GetFileInfo(currentSelectedSave).textureData, param.GetFileInfo(currentSelectedSave).textureWidth, param.GetFileInfo(currentSelectedSave).textureHeight); - } else + if (curSave.texture != NULL) { + curSave.texture->SetTexture(); + tw = curSave.texture->Width(); + th = curSave.texture->Height(); + } else { PPGeDisableTexture(); - PPGeDrawImage(x, y, w, h, 0, 0 ,1 ,1 ,tw, th, textureColor); - if (param.GetFileInfo(currentSelectedSave).textureData != 0) + } + PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor); + if (curSave.texture != NULL) PPGeSetDefaultTexture(); } @@ -956,6 +961,10 @@ int PSPSaveDialog::Update(int animSpeed) case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) param.GetPspParam()->common.result = 0; + else if (param.secureCanSkip(param.GetPspParam(),param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) { + INFO_LOG(SCEUTILITY,"Has not been saved yet, just skip."); + param.GetPspParam()->common.result = 0; + } else param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code status = SCE_UTILITY_STATUS_FINISHED; diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index eafb0d4f7f..fb43101c87 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -166,10 +166,9 @@ void SavedataParam::Init() #ifdef ANDROID int handle = pspFileSystem.OpenFile(savePath + ".nomedia", (FileAccess)(FILEACCESS_CREATE | FILEACCESS_WRITE), 0); if (handle) { - ILOG("Created .nomedia file"); pspFileSystem.CloseFile(handle); } else { - ILOG("Failed to create .nomedia file"); + ELOG("Failed to create .nomedia file"); } #endif } @@ -324,15 +323,11 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save ParamSFOData sfoFile; std::string sfopath = dirPath+"/" + SFO_FILENAME; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); - if(sfoInfo.exists) // Read old sfo if exist + if (sfoInfo.exists) // Read old sfo if exist { - u8 *sfoData = new u8[(size_t)sfoInfo.size]; - size_t sfoSize = (size_t)sfoInfo.size; - if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) - { - sfoFile.ReadSFO(sfoData,sfoSize); - delete[] sfoData; - } + std::vector sfoData; + if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) + sfoFile.ReadSFO(sfoData); } // Update values @@ -567,12 +562,11 @@ void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string di ParamSFOData sfoFile; std::string sfopath = dirPath+"/" + SFO_FILENAME; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); - if(sfoInfo.exists) { - // Read sfo - u8 *sfoData = new u8[(size_t)sfoInfo.size]; - size_t sfoSize = (size_t)sfoInfo.size; - if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) { - sfoFile.ReadSFO(sfoData,sfoSize); + if (sfoInfo.exists) { + // Read sfo + std::vector sfoData; + if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) { + sfoFile.ReadSFO(sfoData); // copy back info in request strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128); @@ -580,10 +574,42 @@ void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string di strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024); param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL"); } - delete[] sfoData; } } +std::set SavedataParam::getSecureFileNames(std::string dirPath) { + PSPFileInfo sfoFileInfo = pspFileSystem.GetFileInfo(dirPath + "/" + SFO_FILENAME); + std::set secureFileNames; + if (!sfoFileInfo.exists) + return secureFileNames; + + ParamSFOData sfoFile; + std::vector sfoData; + if (pspFileSystem.ReadEntireFile(dirPath + "/" + SFO_FILENAME, sfoData) >= 0) { + sfoFile.ReadSFO(sfoData); + } + + u32 sfoFileListSize = 0; + char *sfoFileList = (char *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &sfoFileListSize); + const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3; + const u32 FILE_LIST_COUNT_MAX = 99; + + // Filenames are 13 bytes long at most. Add a NULL so there's no surprises. + char temp[14]; + temp[13] = '\0'; + + for (u32 i = 0; i < FILE_LIST_COUNT_MAX; ++i) { + // Ends at a NULL filename. + if (i * FILE_LIST_ITEM_SIZE >= sfoFileListSize || sfoFileList[i * FILE_LIST_ITEM_SIZE] == '\0') { + break; + } + + strncpy(temp, &sfoFileList[i * FILE_LIST_ITEM_SIZE], 13); + secureFileNames.insert(temp); + } + return secureFileNames; +} + void SavedataParam::LoadFile(const std::string dirPath, const std::string filename, PspUtilitySavedataFileData *fileData) { std::string filePath = dirPath + "/" + filename; s64 readSize = -1; @@ -959,32 +985,7 @@ int SavedataParam::GetFilesList(SceUtilitySavedataParam *param) std::set secureFilenames; // TODO: Error code if not? if (sfoFileInfo.exists) { - ParamSFOData sfoFile; - size_t sfoSize = (size_t)sfoFileInfo.size; - u8 *sfoData = new u8[sfoSize]; - if (ReadPSPFile(dirPath + "/" + SFO_FILENAME, &sfoData, sfoSize, NULL)){ - sfoFile.ReadSFO(sfoData, sfoSize); - } - delete[] sfoData; - - u32 sfoFileListSize = 0; - char *sfoFileList = (char *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &sfoFileListSize); - const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3; - const u32 FILE_LIST_COUNT_MAX = 99; - - // Filenames are 13 bytes long at most. Add a NULL so there's no surprises. - char temp[14]; - temp[13] = '\0'; - - for (u32 i = 0; i < FILE_LIST_COUNT_MAX; ++i) { - // Ends at a NULL filename. - if (i * FILE_LIST_ITEM_SIZE >= sfoFileListSize || sfoFileList[i * FILE_LIST_ITEM_SIZE] == '\0') { - break; - } - - strncpy(temp, &sfoFileList[i * FILE_LIST_ITEM_SIZE], 13); - secureFilenames.insert(temp); - } + secureFilenames = getSecureFileNames(dirPath); } // Does not list directories, nor recurse into them, and ignores files not ALL UPPERCASE. @@ -1085,20 +1086,20 @@ void SavedataParam::Clear() { for (int i = 0; i < saveNameListDataCount; i++) { - if (saveDataList[i].textureData != 0 && saveDataList[i].size != 0) - kernelMemory.Free(saveDataList[i].textureData); - saveDataList[i].textureData = 0; + if (saveDataList[i].texture != NULL && (!noSaveIcon || saveDataList[i].texture != noSaveIcon->texture)) + delete saveDataList[i].texture; + saveDataList[i].texture = NULL; } - delete[] saveDataList; + delete [] saveDataList; saveDataList = 0; saveDataListCount = 0; } if (noSaveIcon) { - if(noSaveIcon->textureData != 0) - kernelMemory.Free(noSaveIcon->textureData); - noSaveIcon->textureData = 0; + if (noSaveIcon->texture != NULL) + delete noSaveIcon->texture; + noSaveIcon->texture = NULL; delete noSaveIcon; noSaveIcon = 0; } @@ -1233,33 +1234,6 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) return 0; } -bool SavedataParam::CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info) -{ - unsigned char *textureData; - int w,h; - - int success = pngLoadPtr(pngData, (int)pngSize, &w, &h, &textureData, false); - - u32 texSize = w*h*4; - u32 atlasPtr; - if (success) - atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); - if (success && atlasPtr != (u32)-1) - { - info.textureData = atlasPtr; - Memory::Memcpy(atlasPtr, textureData, texSize); - free(textureData); - info.textureWidth = w; - info.textureHeight = h; - } - else - { - WARN_LOG(SCEUTILITY, "Unable to load PNG data for savedata."); - return false; - } - return true; -} - void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName) { saveInfo.size = info.size; @@ -1268,7 +1242,12 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std:: saveInfo.modif_time = info.mtime; // Start with a blank slate. - saveInfo.textureData = 0; + if (saveInfo.texture != NULL) { + if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) { + delete saveInfo.texture; + } + saveInfo.texture = NULL; + } saveInfo.title[0] = 0; saveInfo.saveTitle[0] = 0; saveInfo.saveDetail[0] = 0; @@ -1278,28 +1257,22 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std:: std::string fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + ICON0_FILENAME; PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); if (info2.exists) - { - u8 *textureDataPNG = new u8[(size_t)info2.size]; - ReadPSPFile(fileDataPath2, &textureDataPNG, info2.size, NULL); - CreatePNGIcon(textureDataPNG, (int)info2.size, saveInfo); - delete[] textureDataPNG; - } + saveInfo.texture = new PPGeImage(fileDataPath2); // Load info in PARAM.SFO fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + SFO_FILENAME; info2 = pspFileSystem.GetFileInfo(fileDataPath2); if (info2.exists) { - u8 *sfoParam = new u8[(size_t)info2.size]; - ReadPSPFile(fileDataPath2, &sfoParam, info2.size, NULL); + std::vector sfoData; + pspFileSystem.ReadEntireFile(fileDataPath2, sfoData); ParamSFOData sfoFile; - if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) + if (sfoFile.ReadSFO(sfoData)) { SetStringFromSFO(sfoFile, "TITLE", saveInfo.title, sizeof(saveInfo.title)); SetStringFromSFO(sfoFile, "SAVEDATA_TITLE", saveInfo.saveTitle, sizeof(saveInfo.saveTitle)); SetStringFromSFO(sfoFile, "SAVEDATA_DETAIL", saveInfo.saveDetail, sizeof(saveInfo.saveDetail)); } - delete [] sfoParam; } } @@ -1314,7 +1287,12 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName) saveInfo.size = 0; saveInfo.saveName = saveName; saveInfo.idx = 0; - saveInfo.textureData = 0; + if (saveInfo.texture != NULL) { + if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) { + delete saveInfo.texture; + } + saveInfo.texture = NULL; + } if (GetPspParam()->newData.IsValid() && GetPspParam()->newData->buf.IsValid()) { @@ -1323,11 +1301,9 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName) { noSaveIcon = new SaveFileInfo(); PspUtilitySavedataFileData *newData = GetPspParam()->newData; - CreatePNGIcon(newData->buf, (int)newData->size, *noSaveIcon); + noSaveIcon->texture = new PPGeImage(newData->buf.ptr, (SceSize)newData->size); } - saveInfo.textureData = noSaveIcon->textureData; - saveInfo.textureWidth = noSaveIcon->textureWidth; - saveInfo.textureHeight = noSaveIcon->textureHeight; + saveInfo.texture = noSaveIcon->texture; } } @@ -1465,6 +1441,21 @@ int SavedataParam::GetLastEmptySave() return idx; } +int SavedataParam::GetSaveNameIndex(SceUtilitySavedataParam* param) +{ + std::string saveName = GetSaveName(param); + for (int i = 0; i < saveNameListDataCount; i++) + { + // TODO: saveName may contain wildcards + if (saveDataList[i].saveName == saveName) + { + return i; + } + } + + return 0; +} + void SavedataParam::DoState(PointerWrap &p) { auto s = p.Section("SavedataParam", 1); @@ -1501,11 +1492,10 @@ bool SavedataParam::IsSaveEncrypted(SceUtilitySavedataParam* param, const std::s PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if(sfoInfo.exists) // Read sfo { - u8 *sfoData = new u8[(size_t)sfoInfo.size]; - size_t sfoSize = (size_t)sfoInfo.size; - if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) + std::vector sfoData; + if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) { - sfoFile.ReadSFO(sfoData,sfoSize); + sfoFile.ReadSFO(sfoData); // save created in PPSSPP and not encrypted has '0' in SAVEDATA_PARAMS u32 tmpDataSize = 0; @@ -1519,7 +1509,6 @@ bool SavedataParam::IsSaveEncrypted(SceUtilitySavedataParam* param, const std::s } } } - delete[] sfoData; } return isCrypted; } @@ -1531,3 +1520,25 @@ bool SavedataParam::IsInSaveDataList(std::string saveName, int count) { } return false; } + +bool SavedataParam::secureCanSkip(SceUtilitySavedataParam* param, bool secureMode) { + if (!secureMode) // Only check in secure mode. + return false; + std::string dirPath = savePath + GetGameName(param) + GetSaveName(param); + std::string sfoPath = dirPath + "/" + SFO_FILENAME; + std::string secureFileName = GetFileName(param); + std::set secureFileNames; + PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfoPath); + // If sfo doesn't exist,shouldn't skip. + if (!sfoInfo.exists) + return false; + + // Get secure file names from PARAM.SFO. + secureFileNames = getSecureFileNames(dirPath); + // Secure file name should be saved in PARAM.SFO + // Cannot find name in PARAM.SFO, could skip. + if (secureFileNames.find(secureFileName) == secureFileNames.end()) + return true; + + return false; +} diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index cb81383c5f..234fec649c 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -21,6 +21,7 @@ #include "Core/HLE/sceRtc.h" #include "Core/System.h" #include "Core/Dialog/PSPDialog.h" +#include "Core/Util/PPGeDraw.h" #include "Common/CommonTypes.h" #undef st_ctime @@ -250,12 +251,9 @@ struct SaveFileInfo tm modif_time; - u32 textureData; - int textureWidth; - int textureHeight; + PPGeImage *texture; - SaveFileInfo() : size(0), saveName(""), idx(0), - textureData(0), textureWidth(0), textureHeight(0) + SaveFileInfo() : size(0), saveName(""), idx(0), texture(NULL) { memset(title, 0, 128); memset(saveTitle, 0, 128); @@ -265,7 +263,7 @@ struct SaveFileInfo void DoState(PointerWrap &p) { - auto s = p.Section("SaveFileInfo", 1); + auto s = p.Section("SaveFileInfo", 1, 2); if (!s) return; @@ -278,9 +276,30 @@ struct SaveFileInfo p.DoArray(saveDetail, sizeof(saveDetail)); p.Do(modif_time); - p.Do(textureData); - p.Do(textureWidth); - p.Do(textureHeight); + + if (s <= 1) { + u32 textureData; + int textureWidth; + int textureHeight; + p.Do(textureData); + p.Do(textureWidth); + p.Do(textureHeight); + + if (textureData != 0) { + // Must be MODE_READ. + texture = new PPGeImage(""); + texture->CompatLoad(textureData, textureWidth, textureHeight); + } + } else { + bool hasTexture = texture != NULL; + p.Do(hasTexture); + if (hasTexture) { + if (p.mode == p.MODE_READ) { + texture = new PPGeImage(""); + } + texture->DoState(p); + } + } } }; @@ -305,6 +324,7 @@ public: bool GetSize(SceUtilitySavedataParam* param); bool IsSaveEncrypted(SceUtilitySavedataParam* param, const std::string &saveDirName); bool IsInSaveDataList(std::string saveName, int count); + bool secureCanSkip(SceUtilitySavedataParam* param, bool secureMode); std::string GetGameName(SceUtilitySavedataParam* param); std::string GetSaveName(SceUtilitySavedataParam* param); @@ -330,12 +350,12 @@ public: int GetLastDataSave(); int GetFirstEmptySave(); int GetLastEmptySave(); + int GetSaveNameIndex(SceUtilitySavedataParam* param); void DoState(PointerWrap &p); private: void Clear(); - bool CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info); void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName); void SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName); void ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName); @@ -351,6 +371,8 @@ private: int UpdateHash(u8* sfoData, int sfoSize, int sfoDataParamsOffset, int encryptmode); int BuildHash(unsigned char *output, unsigned char *data, unsigned int len, unsigned int alignedLen, int mode, unsigned char *cryptkey); + std::set getSecureFileNames(std::string dirPath); + SceUtilitySavedataParam* pspParam; int selectedSave; SaveFileInfo *saveDataList; diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 78b633a4a1..d82c3adac1 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -29,7 +29,7 @@ const char *ElfReader::GetSectionName(int section) return 0; int nameOffset = sections[section].sh_name; - char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx); + const char *ptr = (const char *)GetSectionDataPtr(header->e_shstrndx); if (ptr) return ptr + nameOffset; @@ -51,10 +51,13 @@ void addrToHiLo(u32 addr, u16 &hi, s16 &lo) } } -void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) +bool ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) { + int numErrors = 0; + DEBUG_LOG(LOADER, "Loading %i relocations...", numRelocs); for (int r = 0; r < numRelocs; r++) { + // INFO_LOG(LOADER, "Loading reloc %i (%p)...", r, rels + r); u32 info = rels[r].r_info; u32 addr = rels[r].r_offset; @@ -66,15 +69,35 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) //0 = code //1 = data + if (readwrite >= (int)ARRAY_SIZE(segmentVAddr)) { + if (numErrors < 10) { + ERROR_LOG_REPORT(LOADER, "Bad segment number %i", readwrite); + } + numErrors++; + continue; + } + addr += segmentVAddr[readwrite]; + // It appears that misaligned relocations are allowed. + // Will they work correctly on big-endian? + + if (((addr & 3) && type != R_MIPS_32) || !Memory::IsValidAddress(addr)) { + if (numErrors < 10) { + WARN_LOG_REPORT(LOADER, "Suspicious address %08x, skipping reloc, type = %d", addr, type); + } else if (numErrors == 10) { + WARN_LOG(LOADER, "Too many bad relocations, skipping logging"); + } + numErrors++; + continue; + } + u32 op = Memory::Read_Instruction(addr).encoding; const bool log = false; //log=true; - if (log) - { - DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info); + if (log) { + DEBUG_LOG(LOADER,"rel at: %08x info: %08x type: %i",addr, info, type); } u32 relocateTo = segmentVAddr[relative]; @@ -107,22 +130,24 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) if ((rels[t].r_info & 0xF) == R_MIPS_LO16) { u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite]; - if (log) - { + if (log) { DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr); } - - s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed?? - cur += lo; - cur += relocateTo; - addrToHiLo(cur, hi, lo); - found = true; - break; + if (Memory::IsValidAddress(corrLoAddr)) { + s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed?? + cur += lo; + cur += relocateTo; + addrToHiLo(cur, hi, lo); + found = true; + break; + } else { + ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr); + } } } - if (!found) + if (!found) { ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16"); - + } op = (op & 0xFFFF0000) | (hi); } break; @@ -164,6 +189,10 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) } Memory::Write_U32(op, addr); } + if (numErrors) { + WARN_LOG(LOADER, "%i bad relocations found!!!", numErrors); + } + return numErrors == 0; } @@ -276,8 +305,8 @@ void ElfReader::LoadRelocations2(int rel_seg) ERROR_LOG_REPORT(LOADER, "Rel2: invalid lo16 type! %x", flag); } - op = Memory::ReadUnchecked_U32(rel_offset); - DEBUG_LOG(LOADER, "Rel2: %5d: CMD=0x%04X type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, type, off_seg, rel_base, addr_seg, op); + op = Memory::Read_Instruction(rel_offset).encoding; + DEBUG_LOG(LOADER, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op); switch(type){ case 0: @@ -289,6 +318,11 @@ void ElfReader::LoadRelocations2(int rel_seg) case 6: // R_MIPS_J26 case 7: // R_MIPS_JAL26 op = (op&0xFC000000) | (((op&0x03FFFFFF)+(relocate_to>>2))&0x03FFFFFF); + // To be safe, let's force it to the specified jump. + if (type == 6) + op = (op & ~0xFC000000) | 0x08000000; + else if (type == 7) + op = (op & ~0xFC000000) | 0x0C000000; break; case 4: // R_MIPS_HI16 addr = ((op<<16)+lo16)+relocate_to; @@ -301,6 +335,7 @@ void ElfReader::LoadRelocations2(int rel_seg) op = (op&0xffff0000) | (((op&0xffff)+relocate_to)&0xffff); break; default: + ERROR_LOG_REPORT(LOADER, "Rel2: unexpected relocation type! %x", type); break; } @@ -436,7 +471,7 @@ int ElfReader::LoadInto(u32 loadAddress) DEBUG_LOG(LOADER,"Relocations:"); // Second pass: Do necessary relocations - for (int i=0; ish_info; - if (sectionToModify >= 0) { if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) @@ -458,8 +492,10 @@ int ElfReader::LoadInto(u32 loadAddress) Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i); - DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify)); - LoadRelocations(rels, numRelocs); + DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s : offset = %08x", name, numRelocs, GetSectionName(sectionToModify), sections[i].sh_offset); + if (!LoadRelocations(rels, numRelocs)) { + WARN_LOG(LOADER, "LoadInto: Relocs failed, trying anyway"); + } } else { @@ -495,28 +531,25 @@ int ElfReader::LoadInto(u32 loadAddress) } // Segment relocations (a few games use them) - if (GetNumSections() == 0) - { - for (int i=0; ie_phnum; i++) + if (GetNumSections() == 0) { + for (int i = 0; i < header->e_phnum; i++) { Elf32_Phdr *p = &segments[i]; - if (p->p_type == 0x700000A0) - { + if (p->p_type == PT_PSPREL1) { INFO_LOG(LOADER,"Loading segment relocations"); - int numRelocs = p->p_filesz / sizeof(Elf32_Rel); Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i); - LoadRelocations(rels, numRelocs); - } else if (p->p_type == 0x700000A1) - { + if (!LoadRelocations(rels, numRelocs)) { + ERROR_LOG(LOADER, "LoadInto: Relocs failed, trying anyway (2)"); + } + } else if (p->p_type == PT_PSPREL2) { INFO_LOG(LOADER,"Loading segment relocations2"); LoadRelocations2(i); } } } - NOTICE_LOG(LOADER,"ELF loading completed successfully."); return SCE_KERNEL_ERROR_OK; } @@ -564,18 +597,18 @@ bool ElfReader::LoadSymbols() if (bRelocate) value += sectionAddrs[sectionIndex]; - SymbolType symtype = ST_DATA; switch (type) { case STT_OBJECT: - symtype = ST_DATA; break; + symbolMap.AddData(value,size,DATATYPE_BYTE); + break; case STT_FUNC: - symtype = ST_FUNCTION; break; + symbolMap.AddFunction(name,value,size); + break; default: continue; } - symbolMap.AddSymbol(name, value, size, symtype); hasSymbols = true; //... } diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index e845b3d5df..f9e9690db2 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -55,7 +55,6 @@ public: bRelocate(false), entryPoint(0), vaddr(0) { - INFO_LOG(LOADER, "ElfReader: %p", ptr); base = (char*)ptr; base32 = (u32 *)ptr; header = (Elf32_Ehdr*)ptr; @@ -117,6 +116,10 @@ public: { return segmentVAddr[segment]; } + u32 GetSegmentDataSize(int segment) + { + return segments[segment].p_filesz; + } bool DidRelocate() { return bRelocate; @@ -135,7 +138,7 @@ public: // More indepth stuff:) int LoadInto(u32 vaddr); bool LoadSymbols(); - void LoadRelocations(Elf32_Rel *rels, int numRelocs); + bool LoadRelocations(Elf32_Rel *rels, int numRelocs); void LoadRelocations2(int rel_seg); diff --git a/Core/ELF/ElfTypes.h b/Core/ELF/ElfTypes.h index afedcd9253..cdc8daf981 100644 --- a/Core/ELF/ElfTypes.h +++ b/Core/ELF/ElfTypes.h @@ -32,6 +32,7 @@ enum ElfType ET_CORE =4, ET_LOPROC =0xFF00, ET_HIPROC =0xFFFF, + ET_PSP_PRX=0xFFA0, }; // Machine/Architecture @@ -78,6 +79,34 @@ enum ElfMachine #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 +// MIPS-specific header flags. +#define EF_MIPS_NOREORDER 0x00000001 +#define EF_MIPS_PIC 0x00000002 +#define EF_MIPS_CPIC 0x00000004 +#define EF_MIPS_XGOT 0x00000008 +#define EF_MIPS_UCODE 0x00000010 +#define EF_MIPS_ABI2 0x00000020 +#define EF_MIPS_DYNAMIC 0x00000040 +#define EF_MIPS_32BITMODE 0x00000100 +#define EF_MIPS_ABI_MASK 0x0000f000 +#define EF_MIPS_ABI_O32 0x00001000 +#define EF_MIPS_ABI_O64 0x00002000 +#define E_MIPS_ABI_EABI32 0x00003000 +#define E_MIPS_ABI_EABI64 0x00004000 +#define EF_MIPS_MACH_MASK 0x00ff0000 +#define EF_MIPS_MACH_PSP 0x00a20000 +#define EF_MIPS_ARCH_MASK 0xf0000000 +#define EF_MIPS_ARCH_1 0x00000000 +#define EF_MIPS_ARCH_2 0x10000000 +#define EF_MIPS_ARCH_3 0x20000000 +#define EF_MIPS_ARCH_4 0x30000000 +#define EF_MIPS_ARCH_5 0x40000000 +#define EF_MIPS_ARCH_32 0x50000000 +#define EF_MIPS_ARCH_64 0x60000000 +#define EF_MIPS_ARCH_32R2 0x70000000 +#define EF_MIPS_ARCH_64R2 0x80000000 + + ///////////////////// // Sections constants @@ -165,6 +194,10 @@ enum ElfSectionFlags #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7FFFFFFF +// Custom segment types +#define PT_PSPREL1 0x700000a0 +#define PT_PSPREL2 0x700000a1 + // Segment flags #define PF_X 1 #define PF_W 2 diff --git a/Core/ELF/PBPReader.cpp b/Core/ELF/PBPReader.cpp index 52672c5dc6..06a17d98d5 100644 --- a/Core/ELF/PBPReader.cpp +++ b/Core/ELF/PBPReader.cpp @@ -23,9 +23,10 @@ #include "Common/FileUtil.h" #include "Core/ELF/PBPReader.h" -PBPReader::PBPReader(const char *filename) : header_() { +PBPReader::PBPReader(const char *filename) : header_(), isELF_(false) { file_ = File::OpenCFile(filename, "rb"); if (!file_) { + ERROR_LOG(LOADER, "Failed to open PBP file %s", filename); return; } @@ -34,6 +35,12 @@ PBPReader::PBPReader(const char *filename) : header_() { fseek(file_, 0, SEEK_SET); fread((char *)&header_, 1, sizeof(header_), file_); if (memcmp(header_.magic, "\0PBP", 4) != 0) { + if (memcmp(header_.magic, "\nFLE", 4) != 0) { + DEBUG_LOG(LOADER, "%s: File actually an ELF, not a PBP", filename); + isELF_ = true; + } else { + ERROR_LOG(LOADER, "Magic number in %s indicated no PBP: %s", filename, header_.magic); + } fclose(file_); file_ = 0; return; diff --git a/Core/ELF/PBPReader.h b/Core/ELF/PBPReader.h index e415c851ce..791365af12 100644 --- a/Core/ELF/PBPReader.h +++ b/Core/ELF/PBPReader.h @@ -43,6 +43,7 @@ public: ~PBPReader(); bool IsValid() const { return file_ != 0; } + bool IsELF() const { return file_ == 0 && isELF_; } // Delete the returned buffer with delete []. u8 *GetSubFile(PBPSubFile file, size_t *outSize); @@ -61,4 +62,5 @@ private: FILE *file_; size_t fileSize_; const PBPHeader header_; -}; \ No newline at end of file + bool isELF_; +}; diff --git a/Core/ELF/ParamSFO.h b/Core/ELF/ParamSFO.h index 90d2a516e7..dfca87f50b 100644 --- a/Core/ELF/ParamSFO.h +++ b/Core/ELF/ParamSFO.h @@ -37,6 +37,10 @@ public: bool ReadSFO(const u8 *paramsfo, size_t size); bool WriteSFO(u8 **paramsfo, size_t *size); + bool ReadSFO(const std::vector ¶msfo) { + return ReadSFO(¶msfo[0], paramsfo.size()); + } + int GetDataOffset(const u8 *paramsfo, std::string dataName); private: diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index d854f53cdd..3dd3e4d412 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -382,11 +382,15 @@ u32 ISOFileSystem::OpenFile(std::string filename, FileAccess access, const char { u32 sectorStart = 0xFFFFFFFF, readSize = 0xFFFFFFFF; parseLBN(filename, §orStart, &readSize); - if (sectorStart >= blockDevice->GetNumBlocks()) + if (sectorStart > blockDevice->GetNumBlocks()) { - WARN_LOG(FILESYS, "Unable to open raw sector: %s, sector %08x, max %08x", filename.c_str(), sectorStart, blockDevice->GetNumBlocks()); + WARN_LOG(FILESYS, "Unable to open raw sector, out of range: %s, sector %08x, max %08x", filename.c_str(), sectorStart, blockDevice->GetNumBlocks()); return 0; } + else if (sectorStart == blockDevice->GetNumBlocks()) + { + ERROR_LOG(FILESYS, "Should not be able to open the block after the last on disc! %08x", sectorStart); + } DEBUG_LOG(FILESYS, "Got a raw sector open: %s, sector %08x, size %08x", filename.c_str(), sectorStart, readSize); u32 newHandle = hAlloc->GetNewHandle(); diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 898af97f41..ae878b7e7a 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -255,6 +255,22 @@ void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) fileSystems.erase(std::remove(fileSystems.begin(), fileSystems.end(), x), fileSystems.end()); } +void MetaFileSystem::Remount(IFileSystem *oldSystem, IFileSystem *newSystem) { + for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) { + if (it->system == oldSystem) { + it->system = newSystem; + } + } +} + +IFileSystem *MetaFileSystem::GetSystem(const std::string &prefix) { + for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) { + if (it->prefix == prefix) + return it->system; + } + return NULL; +} + void MetaFileSystem::Shutdown() { lock_guard guard(lock); @@ -501,6 +517,23 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) return 0; } +int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector &data) { + int error = 0; + u32 handle = pspFileSystem.OpenWithError(error, filename, FILEACCESS_READ); + if (handle == 0) + return error; + + size_t dataSize = (size_t)pspFileSystem.GetFileInfo(filename).size; + data.resize(dataSize); + + size_t result = pspFileSystem.ReadFile(handle, (u8 *)&data[0], dataSize); + pspFileSystem.CloseFile(handle); + + if (result != dataSize) + return SCE_KERNEL_ERROR_ERROR; + return 0; +} + void MetaFileSystem::DoState(PointerWrap &p) { lock_guard guard(lock); diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index b7d99ebc51..126b9c2eff 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -51,6 +51,9 @@ public: void Mount(std::string prefix, IFileSystem *system); void Unmount(std::string prefix, IFileSystem *system); + void Remount(IFileSystem *oldSystem, IFileSystem *newSystem); + + IFileSystem *GetSystem(const std::string &prefix); void ThreadEnded(int threadID); @@ -102,6 +105,9 @@ public: // TODO: void IoCtl(...) + // Convenience helper - returns < 0 on failure. + int ReadEntireFile(const std::string &filename, std::vector &data); + void SetStartingDirectory(const std::string &dir) { lock_guard guard(lock); startingDirectory = dir; diff --git a/Core/Font/PGF.cpp b/Core/Font/PGF.cpp index c7f8689070..86015781cc 100644 --- a/Core/Font/PGF.cpp +++ b/Core/Font/PGF.cpp @@ -30,17 +30,35 @@ // These fonts, created by ttf2pgf, don't have complete glyph info and need to be identified. static bool isJPCSPFont(const char *fontName) { - return !strcmp(fontName, "Liberation") || !strcmp(fontName, "Sazanami") || !strcmp(fontName, "UnDotum"); + return !strcmp(fontName, "Liberation Sans") || !strcmp(fontName, "Liberation Serif") || !strcmp(fontName, "Sazanami") || !strcmp(fontName, "UnDotum") || !strcmp(fontName, "Microsoft YaHei"); } // Gets a number of bits from an offset. -// TODO: Make more efficient. static int getBits(int numBits, const u8 *buf, size_t pos) { - int v = 0; - for (int i = 0; i < numBits; i++) { - v = v | (((buf[pos >> 3] >> (pos & 7)) & 1) << i); - pos++; + _dbg_assert_msg_(SCEFONT, numBits <= 32, "Unable to return more than 32 bits, %d requested", numBits); + + const size_t wordpos = pos >> 5; + const u32 *wordbuf = (const u32 *)buf; + const u8 bitoff = pos & 31; + + // Might just be in one, has to be within two. + if (bitoff + numBits < 32) { + const u32 mask = (1 << numBits) - 1; + return (wordbuf[wordpos] >> bitoff) & mask; + } else { + int v = wordbuf[wordpos] >> bitoff; + + const u8 done = 32 - bitoff; + const u8 remaining = numBits - done; + const u32 mask = (1 << remaining) - 1; + v |= (wordbuf[wordpos + 1] & mask) << done; + return v; } +} + +static inline int consumeBits(int numBits, const u8 *buf, size_t &pos) { + int v = getBits(numBits, buf, pos); + pos += numBits; return v; } @@ -64,8 +82,47 @@ PGF::~PGF() { } } +struct GlyphFromPGF1State { + int x; + int y; + int w; + int h; + int left; + int top; + int flags; + int shadowID; + int advanceH; + int advanceV; + int dimensionWidth, dimensionHeight; + int xAdjustH, xAdjustV; + int yAdjustH, yAdjustV; + u32 ptr; + + operator Glyph() { + Glyph ret; + ret.w = w; + ret.h = h; + ret.left = left; + ret.top = top; + ret.flags = flags; + // Wasn't read before. + ret.shadowFlags = 0; + ret.shadowID = shadowID; + ret.advanceH = advanceH; + ret.advanceV = advanceV; + ret.dimensionWidth = dimensionWidth; + ret.dimensionHeight = dimensionHeight; + ret.xAdjustH = xAdjustH; + ret.xAdjustV = xAdjustV; + ret.yAdjustH = yAdjustH; + ret.yAdjustV = yAdjustV; + ret.ptr = ptr; + return ret; + } +}; + void PGF::DoState(PointerWrap &p) { - auto s = p.Section("PGF", 1); + auto s = p.Section("PGF", 1, 2); if (!s) return; @@ -98,8 +155,22 @@ void PGF::DoState(PointerWrap &p) { p.Do(charmap_compr); p.Do(charmap); - p.Do(glyphs); - p.Do(shadowGlyphs); + if (s == 1) { + std::vector oldGlyphs; + p.Do(oldGlyphs); + glyphs.resize(oldGlyphs.size()); + for (size_t i = 0; i < oldGlyphs.size(); ++i) { + glyphs[i] = oldGlyphs[i]; + } + p.Do(oldGlyphs); + shadowGlyphs.resize(oldGlyphs.size()); + for (size_t i = 0; i < oldGlyphs.size(); ++i) { + shadowGlyphs[i] = oldGlyphs[i]; + } + } else { + p.Do(glyphs); + p.Do(shadowGlyphs); + } p.Do(firstGlyph); } @@ -110,6 +181,8 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) { memcpy(&header, ptr, sizeof(header)); ptr += sizeof(header); + fileName = header.fontName; + if (header.revision == 3) { memcpy(&rev3extra, ptr, sizeof(rev3extra)); rev3extra.compCharMapLength1 &= 0xFFFF; @@ -149,10 +222,8 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) { const u8 *uptr = (const u8 *)wptr; int shadowCharMapSize = ((header.shadowMapLength * header.shadowMapBpe + 31) & ~31) / 8; - u8 *shadowCharMap = new u8[shadowCharMapSize]; - for (int i = 0; i < shadowCharMapSize; i++) { - shadowCharMap[i] = *uptr++; - } + const u8 *shadowCharMap = uptr; + uptr += shadowCharMapSize; const u16_le *sptr = (const u16_le *)uptr; if (header.revision == 3) { @@ -174,17 +245,12 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) { uptr = (const u8 *)sptr; int charMapSize = ((header.charMapLength * header.charMapBpe + 31) & ~31) / 8; - - u8 *charMap = new u8[charMapSize]; - for (int i = 0; i < charMapSize; i++) { - charMap[i] = *uptr++; - } + const u8 *charMap = uptr; + uptr += charMapSize; int charPointerSize = (((header.charPointerLength * header.charPointerBpe + 31) & ~31) / 8); - u8 *charPointerTable = new u8[charPointerSize]; - for (int i = 0; i < charPointerSize; i++) { - charPointerTable[i] = *uptr++; - } + const u8 *charPointerTable = uptr; + uptr += charPointerSize; // PGF Fontdata. u32 fontDataOffset = (u32)(uptr - startPtr); @@ -213,10 +279,6 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) { std::vector charPointers = getTable(charPointerTable, header.charPointerBpe, glyphs.size()); std::vector shadowMap = getTable(shadowCharMap, header.shadowMapBpe, shadowGlyphs.size()); - delete [] charMap; - delete [] shadowCharMap; - delete [] charPointerTable; - // Pregenerate glyphs. for (size_t i = 0; i < glyphs.size(); i++) { GetGlyph(fontData, charPointers[i] * 4 * 8 /* ??? */, FONT_PGF_CHARGLYPH, glyphs[i]); @@ -247,13 +309,18 @@ int PGF::GetCharIndex(int charCode, const std::vector &charmapCompressed) { return -1; } -bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) { +bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo, int altCharCode) { Glyph glyph; memset(charInfo, 0, sizeof(*charInfo)); if (!GetCharGlyph(charCode, FONT_PGF_CHARGLYPH, glyph)) { - // Character not in font, return zeroed charInfo as on real PSP. - return false; + if (charCode < firstGlyph) { + // Character not in font, return zeroed charInfo as on real PSP. + return false; + } + if (!GetCharGlyph(altCharCode, FONT_PGF_CHARGLYPH, glyph)) { + return false; + } } charInfo->bitmapWidth = glyph.w; @@ -262,14 +329,17 @@ bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) { charInfo->bitmapTop = glyph.top; charInfo->sfp26Width = glyph.dimensionWidth; charInfo->sfp26Height = glyph.dimensionHeight; - charInfo->sfp26Ascender = glyph.top << 6; - charInfo->sfp26Descender = (glyph.h - glyph.top) << 6; + charInfo->sfp26Ascender = glyph.yAdjustH; + // Font y goes upwards. If top is 10 and height is 11, the descender is approx. -1 (below 0.) + charInfo->sfp26Descender = charInfo->sfp26Ascender - charInfo->sfp26Height; charInfo->sfp26BearingHX = glyph.xAdjustH; charInfo->sfp26BearingHY = glyph.yAdjustH; charInfo->sfp26BearingVX = glyph.xAdjustV; charInfo->sfp26BearingVY = glyph.yAdjustV; charInfo->sfp26AdvanceH = glyph.advanceH; charInfo->sfp26AdvanceV = glyph.advanceV; + charInfo->shadowFlags = glyph.shadowFlags; + charInfo->shadowId = glyph.shadowID; return true; } @@ -297,7 +367,7 @@ void PGF::GetFontInfo(PGFFontInfo *fi) { fi->maxGlyphWidth = header.maxGlyphWidth; fi->maxGlyphHeight = header.maxGlyphHeight; - fi->charMapLength = header.charMapLength; + fi->numGlyphs = header.charPointerLength; fi->shadowMapLength = 0; // header.shadowMapLength; TODO fi->BPP = header.bpp; @@ -311,40 +381,34 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly if (charPtr + 96 > fontDataSize * 8) return false; } + // Skip size. charPtr += 14; - glyph.w = getBits(7, fontdata, charPtr); - charPtr += 7; + glyph.w = consumeBits(7, fontdata, charPtr); + glyph.h = consumeBits(7, fontdata, charPtr); - glyph.h = getBits(7, fontdata, charPtr); - charPtr += 7; - - glyph.left = getBits(7, fontdata, charPtr); - charPtr += 7; + glyph.left = consumeBits(7, fontdata, charPtr); if (glyph.left >= 64) { glyph.left -= 128; } - glyph.top = getBits(7, fontdata, charPtr); - charPtr += 7; + glyph.top = consumeBits(7, fontdata, charPtr); if (glyph.top >= 64) { glyph.top -= 128; } - glyph.flags = getBits(6, fontdata, charPtr); - charPtr += 6; + glyph.flags = consumeBits(6, fontdata, charPtr); - if (glyph.flags & FONT_PGF_CHARGLYPH) { - // Skip magic number - charPtr += 7; + if (glyphType == FONT_PGF_CHARGLYPH) { + glyph.shadowFlags = consumeBits(2, fontdata, charPtr) << (2 + 3); + glyph.shadowFlags |= consumeBits(2, fontdata, charPtr) << 3; + glyph.shadowFlags |= consumeBits(3, fontdata, charPtr); - glyph.shadowID = getBits(9, fontdata, charPtr); - charPtr += 9; + glyph.shadowID = consumeBits(9, fontdata, charPtr); if ((glyph.flags & FONT_PGF_METRIC_DIMENSION_INDEX) == FONT_PGF_METRIC_DIMENSION_INDEX) { - int dimensionIndex = getBits(8, fontdata, charPtr); - charPtr += 8; + int dimensionIndex = consumeBits(8, fontdata, charPtr); if (dimensionIndex < header.dimTableLength) { glyph.dimensionWidth = dimensionTable[0][dimensionIndex]; @@ -360,16 +424,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly } else { - glyph.dimensionWidth = getBits(32, fontdata, charPtr); - charPtr += 32; - glyph.dimensionHeight = getBits(32, fontdata, charPtr); - charPtr += 32; + glyph.dimensionWidth = consumeBits(32, fontdata, charPtr); + glyph.dimensionHeight = consumeBits(32, fontdata, charPtr); } if ((glyph.flags & FONT_PGF_METRIC_BEARING_X_INDEX) == FONT_PGF_METRIC_BEARING_X_INDEX) { - int xAdjustIndex = getBits(8, fontdata, charPtr); - charPtr += 8; + int xAdjustIndex = consumeBits(8, fontdata, charPtr); if (xAdjustIndex < header.xAdjustTableLength) { glyph.xAdjustH = xAdjustTable[0][xAdjustIndex]; @@ -386,16 +447,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly } else { - glyph.xAdjustH = getBits(32, fontdata, charPtr); - charPtr += 32; - glyph.xAdjustV = getBits(32, fontdata, charPtr); - charPtr += 32; + glyph.xAdjustH = consumeBits(32, fontdata, charPtr); + glyph.xAdjustV = consumeBits(32, fontdata, charPtr); } if ((glyph.flags & FONT_PGF_METRIC_BEARING_Y_INDEX) == FONT_PGF_METRIC_BEARING_Y_INDEX) { - int yAdjustIndex = getBits(8, fontdata, charPtr); - charPtr += 8; + int yAdjustIndex = consumeBits(8, fontdata, charPtr); if (yAdjustIndex < header.xAdjustTableLength) { glyph.yAdjustH = yAdjustTable[0][yAdjustIndex]; @@ -412,18 +470,23 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly } else { - glyph.yAdjustH = getBits(32, fontdata, charPtr); - charPtr += 32; - glyph.yAdjustV = getBits(32, fontdata, charPtr); - charPtr += 32; + glyph.yAdjustH = consumeBits(32, fontdata, charPtr); + glyph.yAdjustV = consumeBits(32, fontdata, charPtr); } - int advanceIndex = getBits(8, fontdata, charPtr); - charPtr += 8; + if ((glyph.flags & FONT_PGF_METRIC_ADVANCE_INDEX) == FONT_PGF_METRIC_ADVANCE_INDEX) + { + int advanceIndex = consumeBits(8, fontdata, charPtr); - if (advanceIndex < header.advanceTableLength) { - glyph.advanceH = advanceTable[0][advanceIndex]; - glyph.advanceV = advanceTable[1][advanceIndex]; + if (advanceIndex < header.advanceTableLength) { + glyph.advanceH = advanceTable[0][advanceIndex]; + glyph.advanceV = advanceTable[1][advanceIndex]; + } + } + else + { + glyph.advanceH = consumeBits(32, fontdata, charPtr); + glyph.advanceV = consumeBits(32, fontdata, charPtr); } } else { glyph.shadowID = 65535; @@ -453,7 +516,7 @@ bool PGF::GetCharGlyph(int charCode, int glyphType, Glyph &glyph) { return true; } -void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType, bool packagedFont) { +void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType) { Glyph glyph; if (!GetCharGlyph(charCode, glyphType, glyph)) { // No Glyph available for this charCode, try to use the alternate char. @@ -472,7 +535,7 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW return; } - u32 bitPtr = glyph.ptr * 8; + size_t bitPtr = glyph.ptr * 8; int numberPixels = glyph.w * glyph.h; int pixelIndex = 0; @@ -481,14 +544,12 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW while (pixelIndex < numberPixels && bitPtr + 8 < fontDataSize * 8) { // This is some kind of nibble based RLE compression. - int nibble = getBits(4, fontData, bitPtr); - bitPtr += 4; + int nibble = consumeBits(4, fontData, bitPtr); int count; int value = 0; if (nibble < 8) { - value = getBits(4, fontData, bitPtr); - bitPtr += 4; + value = consumeBits(4, fontData, bitPtr); count = nibble + 1; } else { count = 16 - nibble; @@ -496,8 +557,7 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW for (int i = 0; i < count && pixelIndex < numberPixels; i++) { if (nibble >= 8) { - value = getBits(4, fontData, bitPtr); - bitPtr += 4; + value = consumeBits(4, fontData, bitPtr); } int xx, yy; @@ -512,10 +572,6 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW int pixelX = x + xx; int pixelY = y + yy; - // Apply offset by 1px for our packaged PSP fonts - if (packagedFont) - pixelX += 1; - if (pixelX >= clipX && pixelX < clipX + clipWidth && pixelY >= clipY && pixelY < clipY + clipHeight) { // 4-bit color value int pixelColor = value; diff --git a/Core/Font/PGF.h b/Core/Font/PGF.h index 127e2f2b46..20848983dd 100644 --- a/Core/Font/PGF.h +++ b/Core/Font/PGF.h @@ -39,6 +39,7 @@ enum { FONT_PGF_METRIC_DIMENSION_INDEX = 0x04, FONT_PGF_METRIC_BEARING_X_INDEX = 0x08, FONT_PGF_METRIC_BEARING_Y_INDEX = 0x10, + FONT_PGF_METRIC_ADVANCE_INDEX = 0x20, FONT_PGF_CHARGLYPH = 0x20, FONT_PGF_SHADOWGLYPH = 0x40, }; @@ -93,13 +94,12 @@ struct PGFFontStyle { struct Glyph { - int x; - int y; int w; int h; int left; int top; int flags; + int shadowFlags; int shadowID; int advanceH; int advanceV; @@ -142,6 +142,7 @@ struct PGFHeader s32_le charMapBpe; s32_le charPointerBpe; + // TODO: This has values in it (0404)... u8 pad1[2]; u8 bpp; u8 pad2[1]; @@ -159,6 +160,7 @@ struct PGFHeader u16_le firstGlyph; u16_le lastGlyph; + // TODO: This has a few 01s in it in the official fonts. u8 pad5[26]; s32_le maxAscender; @@ -211,7 +213,8 @@ struct PGFCharInfo { s32_le sfp26BearingVY; s32_le sfp26AdvanceH; s32_le sfp26AdvanceV; - u8 pad[4]; + s16_le shadowFlags; + s16_le shadowId; }; struct PGFFontInfo { @@ -242,13 +245,14 @@ struct PGFFontInfo { // Bitmap dimensions. s16_le maxGlyphWidth; s16_le maxGlyphHeight; - s32_le charMapLength; // Number of elements in the font's charmap. + s32_le numGlyphs; s32_le shadowMapLength; // Number of elements in the font's shadow charmap. // Font style (used by font comparison functions). PGFFontStyle fontStyle; - s32_le BPP; // Font's BPP. + u8 BPP; // Font's BPP. + u8 pad[3]; }; #pragma pack(pop) @@ -260,9 +264,9 @@ public: void ReadPtr(const u8 *ptr, size_t dataSize); - bool GetCharInfo(int charCode, PGFCharInfo *ci); + bool GetCharInfo(int charCode, PGFCharInfo *ci, int altCharCode); void GetFontInfo(PGFFontInfo *fi); - void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType, bool packagedFont); + void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType); void DoState(PointerWrap &p); diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index b80a51b139..bd5f672a30 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -806,3 +806,13 @@ template void WrapI_ICI() { int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2)); RETURN(retval); } + +template void WrapI_IVVVVUI(){ + u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); + RETURN(retval); +} + +template void WrapI_ICUVIII(){ + u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); + RETURN(retval); +} diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 9396b46d9c..fe0871bc5e 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -27,7 +27,6 @@ #include "../Config.h" #include "ChunkFile.h" #include "FixedSizeQueue.h" -#include "Common/Thread.h" #include "Common/Atomics.h" #include "../../native/base/mutex.h" diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp new file mode 100644 index 0000000000..3dd32c5179 --- /dev/null +++ b/Core/HLE/proAdhoc.cpp @@ -0,0 +1,710 @@ +// TODO: Add license + +#include "util/text/parsers.h" +#include "proAdhoc.h" + +uint32_t fakePoolSize = 0; +SceNetAdhocMatchingContext * contexts = NULL; +int one = 1; +bool friendFinderRunning = false; +SceNetAdhocctlPeerInfo * friends = NULL; +SceNetAdhocctlScanInfo * networks = NULL; +int eventHandlerUpdate = -1; +int threadStatus = ADHOCCTL_STATE_DISCONNECTED; + +int metasocket; +SceNetAdhocctlParameter parameter; +std::thread friendFinderThread; +recursive_mutex peerlock; +SceNetAdhocPdpStat * pdp[255]; +SceNetAdhocPtpStat * ptp[255]; + +int isLocalMAC(const SceNetEtherAddr * addr) { + SceNetEtherAddr saddr; + getLocalMac(&saddr); + + // Compare MAC Addresses + int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN); + + // Return Result + return (match == 0); +} + +int isPDPPortInUse(uint16_t port) { + // Iterate Elements + int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + +int isPTPPortInUse(uint16_t port) { + // Iterate Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + +void addFriend(SceNetAdhocctlConnectPacketS2C * packet) { + // Allocate Structure + SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo)); + // Allocated Structure + if(peer != NULL) { + // Clear Memory + memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo)); + + // Link to existing Peers + peer->next = friends; + + // Save Nickname + peer->nickname = packet->name; + + // Save MAC Address + peer->mac_addr = packet->mac; + + // Save IP Address + peer->ip_addr = packet->ip; + + // Multithreading Lock + peerlock.lock(); + + // Link into Peerlist + friends = peer; + + // Multithreading Unlock + peerlock.unlock(); + } +} + +void changeBlockingMode(int fd, int nonblocking) { + unsigned long on = 1; + unsigned long off = 0; +#ifdef _MSC_VER + if(nonblocking){ + // Change to Non-Blocking Mode + ioctlsocket(fd,FIONBIO,&on); + }else { + // Change to Blocking Mode + ioctlsocket(fd, FIONBIO, &off); + } +#else + if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK); + else { + // Get Flags + int flags = fcntl(fd, F_GETFL); + // Remove Non-Blocking Flag + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } +#endif +} + +int countAvailableNetworks(void) { + // Network Count + int count = 0; + + // Group Reference + SceNetAdhocctlScanInfo * group = networks; + + // Count Groups + for(; group != NULL; group = group->next) count++; + + // Return Network Count + return count; +} + +void deleteAllPDP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(pdp[i] != NULL) { + // Close Socket + closesocket(pdp[i]->id); + + // Free Memory + free(pdp[i]); + + // Delete Reference + pdp[i] = NULL; + } + } +} + +void deleteAllPTP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(ptp[i] != NULL) { + // Close Socket + closesocket(ptp[i]->id); + + // Free Memory + free(ptp[i]); + + // Delete Reference + ptp[i] = NULL; + } + } +} + +void deleteFriendByIP(uint32_t ip) { + // Previous Peer Reference + SceNetAdhocctlPeerInfo * prev = NULL; + + // Peer Pointer + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Peer + if(peer->ip_addr == ip) { + // Multithreading Lock + peerlock.lock(); + + // Unlink Left (Beginning) + if(prev == NULL)friends = peer->next; + + // Unlink Left (Other) + else prev->next = peer->next; + + // Multithreading Unlock + peerlock.unlock(); + + // Free Memory + free(peer); + + // Stop Search + break; + } + + // Set Previous Reference + prev = peer; + } +} + +int findFreeMatchingID(void) { + // Minimum Matching ID + int min = 1; + + // Maximum Matching ID + int max = 0; + + // Find highest Matching ID + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // New Maximum + if(max < item->id) max = item->id; + } + + // Find unoccupied ID + int i = min; for(; i < max; i++) { + // Found unoccupied ID + if(findMatchingContext(i) == NULL) return i; + } + + // Append at virtual end + return max + 1; +} + +SceNetAdhocMatchingContext * findMatchingContext(int id) { + // Iterate Matching Context List + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { // Found Matching ID + if(item->id == id) return item; + } + + // Context not found + return NULL; +} + +void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) { + // End of List + if(node == NULL) return; + + // Increase Recursion Depth + freeFriendsRecursive(node->next); + + // Free Memory + free(node); +} + +int friendFinder(){ + // Receive Buffer + int rxpos = 0; + uint8_t rx[1024]; + + // Chat Packet + SceNetAdhocctlChatPacketC2S chat; + chat.base.opcode = OPCODE_CHAT; + + // Last Ping Time + uint64_t lastping = 0; + + // Last Time Reception got updated + uint64_t lastreceptionupdate = 0; + + uint64_t now; + + // Finder Loop + while(friendFinderRunning) { + // Acquire Network Lock + //_acquireNetworkLock(); + + // Ping Server + now = real_time_now()*1000.0; + if(now - lastping >= 100) { + // Update Ping Time + lastping = now; + + // Prepare Packet + uint8_t opcode = OPCODE_PING; + + // Send Ping to Server + send(metasocket, (const char *)&opcode, 1,0); + } + + // Send Chat Messages + //while(popFromOutbox(chat.message)) + //{ + // // Send Chat to Server + // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0); + //} + + // Wait for Incoming Data + int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0); + + // Free Network Lock + //_freeNetworkLock(); + + // Received Data + if(received > 0) { + // Fix Position + rxpos += received; + + // Log Incoming Traffic + //printf("Received %d Bytes of Data from Server\n", received); + INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received); + } + + // Handle Packets + if(rxpos > 0) { + // BSSID Packet + if(rx[0] == OPCODE_CONNECT_BSSID) { + // Enough Data available + if(rxpos >= (int)sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) { + // Cast Packet + SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx; + // Update BSSID + parameter.bssid.mac_addr = packet->mac; + // Change State + threadStatus = ADHOCCTL_STATE_CONNECTED; + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0)); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C); + } + } + + // Chat Packet + else if(rx[0] == OPCODE_CHAT) { + // Enough Data available + if(rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) { + // Cast Packet + SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx; + + // Fix for Idiots that try to troll the "ME" Nametag + if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); + + // Add Incoming Chat to HUD + //printf("Receive chat message %s", packet->base.message); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlChatPacketS2C); + } + } + + // Connect Packet + else if(rx[0] == OPCODE_CONNECT) { + // Enough Data available + if(rxpos >= (int)sizeof(SceNetAdhocctlConnectPacketS2C)) { + // Log Incoming Peer + INFO_LOG(SCENET,"Incoming Peer Data..."); + + // Cast Packet + SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx; + + // Add User + addFriend(packet); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(getActivePeerCount()); +#else + // setUserCount(getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C); + } + } + + // Disconnect Packet + else if(rx[0] == OPCODE_DISCONNECT) { + // Enough Data available + if(rxpos >= (int)sizeof(SceNetAdhocctlDisconnectPacketS2C)) { + // Log Incoming Peer Delete Request + INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request..."); + + // Cast Packet + SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx; + + // Delete User by IP + deleteFriendByIP(packet->ip); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(_getActivePeerCount()); +#else + //setUserCount(_getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C); + } + } + + // Scan Packet + else if(rx[0] == OPCODE_SCAN) { + // Enough Data available + if(rxpos >= (int)sizeof(SceNetAdhocctlScanPacketS2C)) { + // Log Incoming Network Information + INFO_LOG(SCENET,"Incoming Group Information..."); + // Cast Packet + SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx; + + // Allocate Structure Data + SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo)); + + // Allocated Structure Data + if(group != NULL) + { + // Clear Memory + memset(group, 0, sizeof(SceNetAdhocctlScanInfo)); + + // Link to existing Groups + group->next = networks; + + // Copy Group Name + group->group_name = packet->group; + + // Set Group Host + group->bssid.mac_addr = packet->mac; + + // Link into Group List + networks = group; + } + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlScanPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlScanPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlScanPacketS2C); + } + } + + // Scan Complete Packet + else if(rx[0] == OPCODE_SCAN_COMPLETE) { + // Log Scan Completion + INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response..."); + + // Change State + threadStatus = ADHOCCTL_STATE_DISCONNECTED; + + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0)); + //int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++) + //{ + // // Active Handler + // if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]); + //} + + // Move RX Buffer + memmove(rx, rx + 1, sizeof(rx) - 1); + + // Fix RX Buffer Length + rxpos -= 1; + } + } + // Original value was 10 ms, I think 100 is just fine + sleep_ms(100); + } + + // Log Shutdown + INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread"); + + // Return Success + return 0; +} + +int getActivePeerCount(void) { + // Counter + int count = 0; + + // #ifdef LOCALHOST_AS_PEER + // // Increase for Localhost + // count++; + // #endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Increase Counter + count++; + } + + // Return Result + return count; +} + +int getLocalIp(sockaddr_in * SocketAddress){ +#ifdef _MSC_VER + // Get local host name + char szHostName[128] = ""; + + if(::gethostname(szHostName, sizeof(szHostName))) { + // Error handling + } + // Get local IP addresses + struct hostent *pHost = 0; + pHost = ::gethostbyname(szHostName); + if(pHost) { + memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length); + return 0; + } + return -1; +#else + SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1"); + return 0; +#endif +} + +void getLocalMac(SceNetEtherAddr * addr){ + // Read MAC Address from config + uint8_t mac[ETHER_ADDR_LEN] = {0}; + if (!ParseMacAddress(g_Config.localMacAddress.c_str(), mac)) { + ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.localMacAddress.c_str()); + } + memcpy(addr, mac, ETHER_ADDR_LEN); +} + +int getPTPSocketCount(void) { + // Socket Counter + int counter = 0; + + // Count Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++; + + // Return Socket Count + return counter; +} + +int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ + int iResult = 0; +#ifdef _MSC_VER + WSADATA data; + iResult = WSAStartup(MAKEWORD(2,2),&data); + if(iResult != NOERROR){ + ERROR_LOG(SCENET, "Wsa failed"); + return iResult; + } +#endif + metasocket = (int)INVALID_SOCKET; + metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); + if(metasocket == INVALID_SOCKET){ + ERROR_LOG(SCENET,"invalid socket"); + return -1; + } + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(27312); // Maybe read this from config too + + // Resolve dns + addrinfo * resultAddr; + addrinfo * ptr; + in_addr serverIp; + iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr); + if(iResult != 0){ + ERROR_LOG(SCENET, "Dns error\n"); + return iResult; + } + for(ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next){ + switch(ptr->ai_family){ + case AF_INET: + serverIp = ((sockaddr_in *)ptr->ai_addr)->sin_addr; + } + } + server_addr.sin_addr = serverIp; + iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); + if(iResult == SOCKET_ERROR){ + ERROR_LOG(SCENET,"Socket error"); + return iResult; + } + memset(¶meter,0,sizeof(parameter)); + strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str()); + parameter.channel = 1; // Fake Channel 1 + + // Prepare Login Packet + getLocalMac(¶meter.bssid.mac_addr); + SceNetAdhocctlLoginPacketC2S packet; + packet.base.opcode = OPCODE_LOGIN; + SceNetEtherAddr addres; + getLocalMac(&addres); + packet.mac = addres; + strcpy((char *)packet.name.data, g_Config.sNickName.c_str()); + memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN); + int sent = send(metasocket, (char*)&packet, sizeof(packet), 0); + changeBlockingMode(metasocket,1); // Change to non-blocking + if(sent > 0){ + return 0; + }else{ + return -1; + } +} + +int isBroadcastMAC(const SceNetEtherAddr * addr) { + // Broadcast MAC + if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1; + // Normal MAC + return 0; +} + +int resolveIP(uint32_t ip, SceNetEtherAddr * mac) { + sockaddr_in addr; + getLocalIp(&addr); + uint32 localIp = addr.sin_addr.s_addr; + + if(ip == localIp){ + getLocalMac(mac); + return 0; + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(peer->ip_addr == ip) { + // Copy Data + *mac = peer->mac_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return -1; +} + +int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) { + // Get Local MAC Address + SceNetEtherAddr localMac; + getLocalMac(&localMac); + // Local MAC Requested + if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) { + // Get Local IP Address + sockaddr_in sockAddr; + getLocalIp(&sockAddr); + *ip = sockAddr.sin_addr.s_addr; + return 0; // return succes + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) { + // Copy Data + *ip = peer->ip_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return -1; +} + +int validNetworkName(const SceNetAdhocctlGroupName * group_name) { + // Result + int valid = 1; + + // Name given + if(group_name != NULL) { + // Iterate Name Characters + int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) { + // End of Name + if(group_name->data[i] == 0) break; + + // Not a digit + if(group_name->data[i] < '0' || group_name->data[i] > '9') { + // Not 'A' to 'Z' + if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') { + // Not 'a' to 'z' + if(group_name->data[i] < 'a' || group_name->data[i] > 'z') { + // Invalid Name + valid = 0; + } + } + } + } + } + // Return Result + return valid; +} + +u64 join32(u32 num1, u32 num2){ + return (u64)num2 << 32 | num1; +} + +void split64(u64 num, int buff[]){ + int num1 = (int)(num&firstMask); + int num2 = (int)((num&secondMask)>>32); + buff[0] = num1; + buff[1] = num2; +} diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h new file mode 100644 index 0000000000..818472ae67 --- /dev/null +++ b/Core/HLE/proAdhoc.h @@ -0,0 +1,594 @@ +#pragma once + +#include "base/timeutil.h" +#include "base/mutex.h" +#include "thread/thread.h" +#include "net/resolve.h" + +#include "Common/ChunkFile.h" +#include "Core/Config.h" +#include "Core/CoreTiming.h" +#include "Core/HLE/HLE.h" +#include "Core/HLE/sceNetAdhoc.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelMutex.h" +#include "Core/HLE/sceUtility.h" + +// Net stuff +#ifdef _MSC_VER +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef _MSC_VER +#define PACK +#undef errno +#undef EAGAIN +#undef EINPROGRESS +#undef EISCONN +#define errno WSAGetLastError() +#define EAGAIN WSAEWOULDBLOCK +#define EINPROGRESS WSAEWOULDBLOCK +#define EISCONN WSAEISCONN +#else +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define closesocket close +#define PACK __attribute__((packed)) +#endif + +// psp strutcs and definitions +#define ADHOCCTL_MODE_ADHOC 0 +#define ADHOCCTL_MODE_GAMEMODE 1 + +// Event Types for Event Handler +#define ADHOCCTL_EVENT_CONNECT 1 +#define ADHOCCTL_EVENT_DISCONNECT 2 +#define ADHOCCTL_EVENT_SCAN 3 + +// Internal Thread States +#define ADHOCCTL_STATE_DISCONNECTED 0 +#define ADHOCCTL_STATE_CONNECTED 1 +#define ADHOCCTL_STATE_SCANNING 2 +#define ADHOCCTL_STATE_GAMEMODE 3 + +// Kernel Utility Netconf Adhoc Types +#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2 +#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4 +#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5 + +// Kernel Utility States +#define UTILITY_NETCONF_STATUS_NONE 0 +#define UTILITY_NETCONF_STATUS_INITIALIZE 1 +#define UTILITY_NETCONF_STATUS_RUNNING 2 +#define UTILITY_NETCONF_STATUS_FINISHED 3 +#define UTILITY_NETCONF_STATUS_SHUTDOWN 4 + +// PTP Connection States +#define PTP_STATE_CLOSED 0 +#define PTP_STATE_LISTEN 1 +#define PTP_STATE_ESTABLISHED 4 + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif +// Ethernet Address +#define ETHER_ADDR_LEN 6 +typedef struct SceNetEtherAddr { + uint8_t data[ETHER_ADDR_LEN]; +} PACK SceNetEtherAddr; + + +// Adhoc Virtual Network Name +#define ADHOCCTL_GROUPNAME_LEN 8 +typedef struct SceNetAdhocctlGroupName { + uint8_t data[ADHOCCTL_GROUPNAME_LEN]; +} PACK SceNetAdhocctlGroupName; + +// Virtual Network Host Information +typedef struct SceNetAdhocctlBSSId { + SceNetEtherAddr mac_addr; + uint8_t padding[2]; +} PACK SceNetAdhocctlBSSId; + +// Virtual Network Information +typedef struct SceNetAdhocctlScanInfo { + struct SceNetAdhocctlScanInfo * next; + s32_le channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + s32_le mode; +} PACK SceNetAdhocctlScanInfo; + +// Player Nickname +#define ADHOCCTL_NICKNAME_LEN 128 +typedef struct SceNetAdhocctlNickname { + uint8_t data[ADHOCCTL_NICKNAME_LEN]; +} PACK SceNetAdhocctlNickname; + +// Active Virtual Network Information +typedef struct SceNetAdhocctlParameter { + s32_le channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + SceNetAdhocctlNickname nickname; +} PACK SceNetAdhocctlParameter; + +// Peer Information +typedef struct SceNetAdhocctlPeerInfo { + SceNetAdhocctlPeerInfo * next; + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + u32_le ip_addr; + uint8_t padding[2]; + u64_le last_recv; +} PACK SceNetAdhocctlPeerInfo; + +// Peer Information with u32 pointers +typedef struct SceNetAdhocctlPeerInfoEmu { + u32_le next; // Changed the pointer to u32 + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + u32_le ip_addr; + u32 padding; // Changed the pointer to u32 + u64_le last_recv; +} SceNetAdhocctlPeerInfoEmu; + +// Game Mode Peer List +#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 +typedef struct SceNetAdhocctlGameModeInfo { + s32_le num; + SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; +} PACK SceNetAdhocctlGameModeInfo; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +// Adhoc ID (Game Product Key) +#define ADHOCCTL_ADHOCID_LEN 9 +typedef struct SceNetAdhocctlAdhocId { + s32_le type; + uint8_t data[ADHOCCTL_ADHOCID_LEN]; + uint8_t padding[3]; +} SceNetAdhocctlAdhocId; + +// Socket Polling Event Listener +struct SceNetAdhocPollSd { + s32_le id; + s32_le events; + s32_le revents; +}; + +// PDP Socket Status +struct SceNetAdhocPdpStat { + struct SceNetAdhocPdpStat * next; + s32_le id; + SceNetEtherAddr laddr; + u16_le lport; + u32_le rcv_sb_cc; +}; + +// PTP Socket Status +struct SceNetAdhocPtpStat { + u32_le next; // Changed the pointer to u32 + s32_le id; + SceNetEtherAddr laddr; + SceNetEtherAddr paddr; + u16_le lport; + u16_le pport; + u32_le snd_sb_cc; + u32_le rcv_sb_cc; + s32_le state; +}; + +// Gamemode Optional Peer Buffer Data +struct SceNetAdhocGameModeOptData { + u32_le size; + u32_le flag; + u64_le last_recv; +}; + +// Gamemode Buffer Status +struct SceNetAdhocGameModeBufferStat { + struct SceNetAdhocGameModeBufferStat * next; + s32_le id; + void * ptr; + u32_le size; + u32_le master; + SceNetAdhocGameModeOptData opt; +}; + + +// Internal Matching Peer Information +typedef struct SceNetAdhocMatchingMemberInternal { + // Next Peer + struct SceNetAdhocMatchingMemberInternal * next; + + // MAC Address + SceNetEtherAddr mac; + + // State Variable + s32_le state; + + // Send in Progress + s32_le sending; + + // Last Heartbeat + u64_le lastping; +} SceNetAdhocMatchingMemberInternal; + + +// Matching handler +struct SceNetAdhocMatchingHandlerArgs { + s32_le id; + s32_le event; + SceNetEtherAddr * peer; + s32_le optlen; + void * opt; +}; + +struct SceNetAdhocMatchingHandler { + u32_le entryPoint; +}; + +// Thread Message Stack Item +typedef struct ThreadMessage { + // Next Thread Message + struct ThreadMessage * next; + + // Stack Event Opcode + u32_le opcode; + + // Target MAC Address + SceNetEtherAddr mac; + + // Optional Data Length + s32_le optlen; +} ThreadMessage; + +// Established Peer + +// Context Information +typedef struct SceNetAdhocMatchingContext { + // Next Context + struct SceNetAdhocMatchingContext * next; + + // Externally Visible ID + s32_le id; + + // Matching Mode (HOST, CLIENT, P2P) + s32_le mode; + + // Running Flag (1 = running, 0 = created) + s32_le running; + + // Maximum Number of Peers (for HOST, P2P) + s32_le maxpeers; + + // Local MAC Address + SceNetEtherAddr mac; + + // Peer List for Connectees + SceNetAdhocMatchingMemberInternal * peerlist; + + // Local PDP Port + u16_le port; + + // Local PDP Socket + s32_le socket; + + // Receive Buffer Length + s32_le rxbuflen; + + // Receive Buffer + uint8_t * rxbuf; + + // Hello Broadcast Interval (Microseconds) + u32_le hello_int; + + // Keep-Alive Broadcast Interval (Microseconds) + u32_le keepalive_int; + + // Resend Interval (Microseconds) + u32_le resend_int; + + // Resend-Counter + s32_le resendcounter; + + // Keep-Alive Counter + s32_le keepalivecounter; + + // Event Handler + SceNetAdhocMatchingHandler handler; + + // Hello Data Length + u32_le hellolen; + + // Hello Data + void * hello; + + // Event Caller Thread + s32_le event_thid; + + // IO Handler Thread + s32_le input_thid; + + // Event Caller Thread Message Stack + s32_le event_stack_lock; + ThreadMessage * event_stack; + + // IO Handler Thread Message Stack + s32_le input_stack_lock; + ThreadMessage * input_stack; +} SceNetAdhocMatchingContext; + +// End of psp definitions + +#define OPCODE_PING 0 +#define OPCODE_LOGIN 1 +#define OPCODE_CONNECT 2 +#define OPCODE_DISCONNECT 3 +#define OPCODE_SCAN 4 +#define OPCODE_SCAN_COMPLETE 5 +#define OPCODE_CONNECT_BSSID 6 +#define OPCODE_CHAT 7 + +// PSP Product Code +#define PRODUCT_CODE_LENGTH 9 + +#ifdef _MSC_VER +#pragma pack(push,1) +#endif + +typedef struct { + // Game Product Code (ex. ULUS12345) + char data[PRODUCT_CODE_LENGTH]; +} PACK SceNetAdhocctlProductCode; + +// Basic Packet +typedef struct { + uint8_t opcode; +} PACK SceNetAdhocctlPacketBase; + +// C2S Login Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; + SceNetAdhocctlNickname name; + SceNetAdhocctlProductCode game; +} PACK SceNetAdhocctlLoginPacketC2S; + +// C2S Connect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; +} PACK SceNetAdhocctlConnectPacketC2S; + +// C2S Chat Packet +typedef struct { + SceNetAdhocctlPacketBase base; + char message[64]; +} PACK SceNetAdhocctlChatPacketC2S; + +// S2C Connect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlNickname name; + SceNetEtherAddr mac; + uint32_t ip; +} PACK SceNetAdhocctlConnectPacketS2C; + +// S2C Disconnect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + uint32_t ip; +} PACK SceNetAdhocctlDisconnectPacketS2C; + +// S2C Scan Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; + SceNetEtherAddr mac; +} PACK SceNetAdhocctlScanPacketS2C; + +// S2C Connect BSSID Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; +} PACK SceNetAdhocctlConnectBSSIDPacketS2C; + +// S2C Chat Packet +typedef struct { + SceNetAdhocctlChatPacketC2S base; + SceNetAdhocctlNickname name; +} PACK SceNetAdhocctlChatPacketS2C; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +// Aux vars +extern int metasocket; +extern SceNetAdhocctlParameter parameter; +extern std::thread friendFinderThread; +extern recursive_mutex peerlock; +extern SceNetAdhocPdpStat * pdp[255]; +extern SceNetAdhocPtpStat * ptp[255]; + +extern uint32_t fakePoolSize; +extern SceNetAdhocMatchingContext * contexts; +extern int one; +extern bool friendFinderRunning; +extern SceNetAdhocctlPeerInfo * friends; +extern SceNetAdhocctlScanInfo * networks; +extern int eventHandlerUpdate; +extern int threadStatus; +// End of Aux vars + +/** + * Local MAC Check + * @param saddr To-be-checked MAC Address + * @return 1 if valid or... 0 + */ +int isLocalMAC(const SceNetEtherAddr * addr); + +/** + * PDP Port Check + * @param port To-be-checked Port + * @return 1 if in use or... 0 + */ +int isPDPPortInUse(uint16_t port); + +/** + * Check whether PTP Port is in use or not + * @param port To-be-checked Port Number + * @return 1 if in use or... 0 + */ +int isPTPPortInUse(uint16_t port); + +/** + * Add Friend to Local List + * @param packet Friend Information + */ +void addFriend(SceNetAdhocctlConnectPacketS2C * packet); + +/** + * Changes the Blocking Mode of the socket + * @param fd File Descriptor of the socket + * @param nonblocking 1 to set to nonblock and 0 to set blocking + */ +void changeBlockingMode(int fd, int nonblocking); + +/** + * Count Virtual Networks by analyzing the Friend List + * @return Number of Virtual Networks + */ +int countAvailableNetworks(); + +/** + * Closes & Deletes all PDP Sockets + */ +void deleteAllPDP(void); + +/** + * Closes & Deletes all PTP sockets + */ +void deleteAllPTP(void); + +/** + * Delete Friend from Local List + * @param ip Friend IP + */ +void deleteFriendByIP(uint32_t ip); + +/** + * Find Free Matching ID + * @return First unoccupied Matching ID + */ +int findFreeMatchingID(void); + +/** + * Find Internal Matching Context for Matching ID + * @param id Matching ID + * @return Matching Context Pointer or... NULL + */ +SceNetAdhocMatchingContext * findMatchingContext(int id); + +/** + * Recursive Memory Freeing-Helper for Friend-Structures + * @param node Current Node in List + */ +void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node); + +/** + * Friend Finder Thread (Receives Peer Information) + * @param args Length of argp in Bytes (Unused) + * @param argp Argument (Unused) + * @return Unused Value - Return 0 + */ +int friendFinder(); + +/** + * Return Number of active Peers in the same Network as the Local Player + * @return Number of active Peers + */ +int getActivePeerCount(void); + +/** + * Returns the locall Ip of this machine, TODO: Implement the linux version + * @param SocketAddres OUT: local ip + */ +int getLocalIp(sockaddr_in * SocketAddress); + +/** + * Joins two 32 bits number into a 64 bit one + * @param num1: first number + * @param num2: second number + * @return Single 64 bit number + */ +#define firstMask 0x00000000FFFFFFFF +#define secondMask 0xFFFFFFFF00000000 +u64 join32(u32 num1, u32 num2); + +/** + * Splits a 64 bit number into two 32 bit ones + * @param num: The number to be split + * @param buf OUT: Array containing the split numbers + */ +void split64(u64 num, int buff[]); + +/** + * Returns the local mac, TODO: Read from Config file + * @param addr OUT: Local Mac + */ +void getLocalMac(SceNetEtherAddr * addr); + +/** + * PTP Socket Counter + * @return Number of internal PTP Sockets + */ +int getPTPSocketCount(void); + +/** + * Initialize Networking Components for Adhocctl Emulator + * @param adhoc_id Game Product Code + * @param server_ip Server IP + * @return 0 on success or... -1 + */ +int initNetwork(SceNetAdhocctlAdhocId *adhocid); + +/** + * Broadcast MAC Check + * @param addr To-be-checked MAC Address + * @return 1 if Broadcast MAC or... 0 + */ +int isBroadcastMAC(const SceNetEtherAddr * addr); + +/** + * Resolve IP to MAC + * @param ip Peer IP Address + * @param mac OUT: Peer MAC + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int resolveIP(uint32_t ip, SceNetEtherAddr * mac); + +/** + * Resolve MAC to IP + * @param mac Peer MAC Address + * @param ip OUT: Peer IP + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip); + +/** + * Check whether Network Name contains only valid symbols + * @param group_name To-be-checked Network Name + * @return 1 if valid or... 0 + */ + int validNetworkName(const SceNetAdhocctlGroupName * groupname); diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6a74c32ab0..b7db665f4c 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -722,6 +722,10 @@ u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 bufferInfoAdd // minWritebytes should not be bigger than writeablebytes minWritebytes = std::min(minWritebytes, (int)atrac->first.writableBytes); + if (atrac->first.fileoffset <= 2*atrac->atracBufSize){ + Sampleoffset = atrac->first.fileoffset; + } + // If we've already loaded everything, the answer is 0. if (atrac->first.size >= atrac->first.filesize) { Sampleoffset = 0; @@ -1871,7 +1875,6 @@ const HLEFunction sceAtrac3plus[] = { {0x0C116E1B,WrapI_IUUUU,"sceAtracLowLevelDecode"}, }; - void Register_sceAtrac3plus() { // Two names RegisterModule("sceATRAC3plus_Library", ARRAY_SIZE(sceAtrac3plus), sceAtrac3plus); diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 965cd75532..b8fe0af817 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -141,7 +141,7 @@ u32 sceAudioOutput(u32 chan, int vol, u32 samplePtr) { u32 sceAudioOutputPanned(u32 chan, int leftvol, int rightvol, u32 samplePtr) { if (leftvol > 0xFFFF || rightvol > 0xFFFF) { - ERROR_LOG(SCEAUDIO, "sceAudioOutputPannedBlocking() - invalid volume"); + ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - invalid volume"); return SCE_ERROR_AUDIO_INVALID_VOLUME; } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - bad channel"); @@ -167,8 +167,9 @@ int sceAudioGetChannelRestLen(u32 chan) { ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x) - bad channel", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } - DEBUG_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x)", chan); - return (int)chans[chan].sampleQueue.size() / 2; + int remainingSamples = (int)chans[chan].sampleQueue.size() / 2; + DEBUG_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLen(%08x)", remainingSamples, chan); + return remainingSamples; } int sceAudioGetChannelRestLength(u32 chan) { @@ -176,8 +177,9 @@ int sceAudioGetChannelRestLength(u32 chan) { ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x) - bad channel", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } - DEBUG_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x)", chan); - return (int)chans[chan].sampleQueue.size() / 2; + int remainingSamples = (int)chans[chan].sampleQueue.size() / 2; + DEBUG_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLength(%08x)", remainingSamples, chan); + return remainingSamples; } static u32 GetFreeChannel() { @@ -438,7 +440,7 @@ const HLEFunction sceAudio[] = {0x5EC81C55, WrapU_IUU, "sceAudioChReserve"}, {0x6FC46853, WrapU_U, "sceAudioChRelease"}, {0xE9D97901, WrapI_U, "sceAudioGetChannelRestLen"}, - {0xB011922F, WrapI_U, "sceAudioGetChannelRestLength"}, + {0xB011922F, WrapI_U, "sceAudioGetChannelRestLength"}, {0xCB2E439E, WrapU_UU, "sceAudioSetChannelDataLen"}, {0x95FD0C2D, WrapU_UU, "sceAudioChangeChannelConfig"}, {0xB7E1D8E7, WrapU_UUU, "sceAudioChangeChannelVolume"}, diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 27bcfda8ff..ad99f5f649 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -114,7 +114,7 @@ void __CtrlUpdateLatch() latch.btnMake |= buttons & changed; latch.btnBreak |= ctrlOldButtons & changed; latch.btnPress |= buttons; - latch.btnRelease |= (ctrlOldButtons & ~buttons) & changed; + latch.btnRelease |= ~buttons; dialogBtnMake |= buttons & changed; ctrlLatchBufs++; @@ -195,10 +195,8 @@ void __CtrlSetRapidFire(bool state) emuRapidFire = state; } -int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative) +int __CtrlReadSingleBuffer(PSPPointer<_ctrl_data> data, bool negative) { - PSPPointer<_ctrl_data> data; - data = ctrlDataPtr; if (data.IsValid()) { *data = ctrlBufs[ctrlBufRead]; @@ -238,11 +236,10 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) ctrlBufRead = (ctrlBuf - availBufs + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS; int done = 0; + PSPPointer<_ctrl_data> data; + data = ctrlDataPtr; for (u32 i = 0; i < availBufs; ++i) - { - done += __CtrlReadSingleBuffer(ctrlDataPtr, negative); - ctrlDataPtr += sizeof(_ctrl_data); - } + done += __CtrlReadSingleBuffer(data++, negative); if (peek) ctrlBufRead = resetRead; @@ -268,7 +265,8 @@ retry: if (wVal == 0) goto retry; - u32 ctrlDataPtr = __KernelGetWaitValue(threadID, error); + PSPPointer<_ctrl_data> ctrlDataPtr; + ctrlDataPtr = __KernelGetWaitValue(threadID, error); int retVal = __CtrlReadSingleBuffer(ctrlDataPtr, wVal == CTRL_WAIT_NEGATIVE); __KernelResumeThreadFromWait(threadID, retVal); } @@ -325,7 +323,7 @@ void __CtrlDoState(PointerWrap &p) { std::lock_guard guard(ctrlMutex); - auto s = p.Section("sceCtrl", 1, 2); + auto s = p.Section("sceCtrl", 1, 3); if (!s) return; @@ -334,7 +332,10 @@ void __CtrlDoState(PointerWrap &p) p.Do(ctrlOldButtons); p.DoVoid(ctrlBufs, sizeof(ctrlBufs)); - p.Do(ctrlCurrent); + if (s <= 2) { + _ctrl_data dummy = {0}; + p.Do(dummy); + } p.Do(ctrlBuf); p.Do(ctrlBufRead); p.Do(latch); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 020fb8d671..1b126ab2a0 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -18,6 +18,7 @@ #include #include #include +#include // TODO: Move the relevant parts into common. Don't want the core // to be dependent on "native", I think. Or maybe should get rid of common @@ -29,7 +30,6 @@ #include "gfx_es2/gl_state.h" #endif -#include "Common/Thread.h" #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" #include "Core/Reporting.h" @@ -81,7 +81,7 @@ static int afterFlipEvent = -1; // hCount is computed now. static int vCount; // The "AccumulatedHcount" can be adjusted, this is the base. -static double hCountBase; +static u32 hCountBase; static int isVblank; static int numSkippedFrames; static bool hasSetMode; @@ -96,7 +96,7 @@ static double nextFrameTime; static int numVBlanksSinceFlip; static u64 frameStartTicks; -const float hCountPerVblank = 285.72f; // insprired by jpcsp +const int hCountPerVblank = 286; std::vector vblankWaitingThreads; @@ -111,7 +111,7 @@ std::vector vblankListeners; // The vblank period is 731.5 us (0.7315 ms) const double vblankMs = 0.7315; -const double frameMs = 1000.0 / 60.0; +const double frameMs = 1001.0 / 60.0; enum { PSP_DISPLAY_SETBUF_IMMEDIATE = 0, @@ -139,6 +139,8 @@ void hleAfterFlip(u64 userdata, int cyclesLate); void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId); void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId); +int __DisplayGetFlipCount() { return actualFlips; } +int __DisplayGetVCount() { return vCount; } void __DisplayInit() { gpuStats.Reset(); @@ -164,7 +166,7 @@ void __DisplayInit() { CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0); isVblank = 0; vCount = 0; - hCountBase = 0.0; + hCountBase = 0; curFrameTime = 0.0; nextFrameTime = 0.0; @@ -183,7 +185,7 @@ void __DisplayInit() { } void __DisplayDoState(PointerWrap &p) { - auto s = p.Section("sceDisplay", 1, 2); + auto s = p.Section("sceDisplay", 1, 3); if (!s) return; @@ -192,7 +194,13 @@ void __DisplayDoState(PointerWrap &p) { p.Do(framebufIsLatched); p.Do(frameStartTicks); p.Do(vCount); - p.Do(hCountBase); + if (s <= 2) { + double oldHCountBase; + p.Do(oldHCountBase); + hCountBase = (int) oldHCountBase; + } else { + p.Do(hCountBase); + } p.Do(isVblank); p.Do(hasSetMode); p.Do(mode); @@ -290,6 +298,7 @@ void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId) { } int vcountUnblock = vblankPausedWaits[pauseKey]; + vblankPausedWaits.erase(pauseKey); if (vcountUnblock <= vCount) { __KernelResumeThreadFromWait(threadID, 0); return; @@ -307,6 +316,10 @@ void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps) { *out_actual_fps = actualFps; } +void __DisplayGetVPS(float *out_vps) { + *out_vps = fps; +} + void __DisplayGetAveragedFPS(float *out_vps, float *out_fps) { float avg = 0.0; if (fpsHistoryValid > 0) { @@ -464,7 +477,7 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { } else { // Wait until we've caught up. while (time_now_d() < nextFrameTime) { - Common::SleepCurrentThread(1); + sleep_ms(1); // Sleep for 1ms on this thread time_update(); } } @@ -497,9 +510,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { } frameStartTicks = CoreTiming::GetTicks(); - // Fire the vblank listeners before we wake threads. - __DisplayFireVblank(); - // Wake up threads waiting for VBlank u32 error; for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { @@ -550,7 +560,8 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { gpuStats.numFlips++; bool throttle, skipFrame; - DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.0f / 60.0f)); + // 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have. + DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.001f / 60.0f)); // Max 4 skipped frames in a row - 15 fps is really the bare minimum for playability. // We check for 3 here so it's 3 skipped frames, 1 non skipped, 3 skipped, etc. @@ -584,6 +595,9 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) { isVblank = 0; DEBUG_LOG(SCEDISPLAY,"Leave VBlank %i", (int)userdata - 1); CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata); + + // Fire the vblank listeners after the vblank completes. + __DisplayFireVblank(); } u32 sceDisplayIsVblank() { diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index 2bec04537c..cce482a410 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -35,4 +35,7 @@ void __DisplayListenVblank(VblankCallback callback); void __DisplayGetDebugStats(char stats[2048]); void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps); +void __DisplayGetVPS(float *out_vps); void __DisplayGetAveragedFPS(float *out_vps, float *out_fps); +int __DisplayGetVCount(); +int __DisplayGetFlipCount(); diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index c5e82b72a3..36191f743c 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -20,6 +20,7 @@ #include "Core/MemMap.h" #include "Core/Reporting.h" #include "Core/HLE/HLE.h" +#include "Core/Debugger/Breakpoints.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" @@ -41,6 +42,10 @@ void __DmacDoState(PointerWrap &p) { int __DmacMemcpy(u32 dst, u32 src, u32 size) { Memory::Memcpy(dst, Memory::GetPointer(src), size); +#ifndef USING_GLES2 + CBreakPoints::ExecMemCheck(src, false, size, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dst, true, size, currentMIPS->pc); +#endif src &= ~0x40000000; dst &= ~0x40000000; diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index 9d23192f21..a015d37fe6 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -104,7 +104,6 @@ class LoadedFont; class FontLib; class Font; int GetInternalFontIndex(Font *font); -bool packagedFont; // These should not need to be state saved. static std::vector internalFonts; @@ -130,30 +129,19 @@ public: } Font(const u8 *data, size_t dataSize) { - pgf_.ReadPtr(data, dataSize); - style_.fontH = (float)pgf_.header.hSize / 64.0f; - style_.fontV = (float)pgf_.header.vSize / 64.0f; - style_.fontHRes = (float)pgf_.header.hResolution / 64.0f; - style_.fontVRes = (float)pgf_.header.vResolution / 64.0f; + Init(data, dataSize); } Font(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) { - pgf_.ReadPtr(data, dataSize); - style_.fontH = entry.hSize / 64.f; - style_.fontV = entry.vSize / 64.f; - style_.fontHRes = entry.hResolution / 64.f; - style_.fontVRes = entry.vResolution / 64.f; - style_.fontWeight = (float)entry.weight; - style_.fontFamily = (u16)entry.familyCode; - style_.fontStyle = (u16)entry.style; - style_.fontStyleSub = (u16)entry.styleSub; - style_.fontLanguage = (u16)entry.languageCode; - style_.fontRegion = (u16)entry.regionCode; - style_.fontCountry = (u16)entry.countryCode; - strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName)); - strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName)); - style_.fontAttributes = entry.extraAttributes; - style_.fontExpire = entry.expireDate; + Init(data, dataSize, entry); + } + + Font (const std::vector &data) { + Init(&data[0], data.size()); + } + + Font (const std::vector &data, const FontRegistryEntry &entry) { + Init(&data[0], data.size(), entry); } const PGFFontStyle &GetFontStyle() const { return style_; } @@ -210,6 +198,33 @@ public: } private: + void Init(const u8 *data, size_t dataSize) { + pgf_.ReadPtr(data, dataSize); + style_.fontH = (float)pgf_.header.hSize / 64.0f; + style_.fontV = (float)pgf_.header.vSize / 64.0f; + style_.fontHRes = (float)pgf_.header.hResolution / 64.0f; + style_.fontVRes = (float)pgf_.header.vResolution / 64.0f; + } + + void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) { + pgf_.ReadPtr(data, dataSize); + style_.fontH = entry.hSize / 64.f; + style_.fontV = entry.vSize / 64.f; + style_.fontHRes = entry.hResolution / 64.f; + style_.fontVRes = entry.vResolution / 64.f; + style_.fontWeight = (float)entry.weight; + style_.fontFamily = (u16)entry.familyCode; + style_.fontStyle = (u16)entry.style; + style_.fontStyleSub = (u16)entry.styleSub; + style_.fontLanguage = (u16)entry.languageCode; + style_.fontRegion = (u16)entry.regionCode; + style_.fontCountry = (u16)entry.countryCode; + strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName)); + strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName)); + style_.fontAttributes = entry.extraAttributes; + style_.fontExpire = entry.expireDate; + } + PGF pgf_; PGFFontStyle style_; DISALLOW_COPY_AND_ASSIGN(Font); @@ -338,6 +353,7 @@ public: } } u32 args[2] = { params_.userDataAddr, (u32)handle_ }; + // TODO: The return value of this is leaking. __KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false); handle_ = 0; fonts_.clear(); @@ -498,28 +514,17 @@ void __LoadInternalFonts() { if (info.exists) { INFO_LOG(SCEFONT, "Loading font %s (%i bytes)", fontFilename.c_str(), (int)info.size); - u8 *buffer = new u8[(size_t)info.size]; - u32 handle = pspFileSystem.OpenFile(fontFilename, FILEACCESS_READ); - if (!handle) { + std::vector buffer; + if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) { ERROR_LOG(SCEFONT, "Failed opening font"); - delete [] buffer; continue; - } - // Our provided font of jpn0.pgf has size 4367080 bytes - // This is an ugly hack to workaround incorrect metrics in it. - if (std::string(entry.fileName) == "jpn0.pgf" && (int)info.size == 4367080) { - packagedFont = true; } - - pspFileSystem.ReadFile(handle, buffer, info.size); - pspFileSystem.CloseFile(handle); - internalFonts.push_back(new Font(buffer, (size_t)info.size, entry)); + internalFonts.push_back(new Font(buffer, entry)); - delete [] buffer; - INFO_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str()); + DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str()); } else { - INFO_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str()); + WARN_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str()); } } } @@ -706,13 +711,9 @@ u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u32 error return 0; } - u8 *buffer = new u8[(size_t)info.size]; - - u32 fileHandle = pspFileSystem.OpenFile(fileName, FILEACCESS_READ); - pspFileSystem.ReadFile(fileHandle, buffer, info.size); - pspFileSystem.CloseFile(fileHandle); - - LoadedFont *font = fontLib->OpenFont(new Font(buffer, (size_t)info.size)); + std::vector buffer; + pspFileSystem.ReadEntireFile(fileName, buffer); + LoadedFont *font = fontLib->OpenFont(new Font(buffer)); if (font) { fontMap[font->Handle()] = font; Memory::Write_U32(0, errorCodePtr); @@ -825,8 +826,10 @@ int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) { } DEBUG_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr); + auto fontLib = font->GetFontLib(); + int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode(); auto charInfo = Memory::GetStruct(charInfoPtr); - font->GetPGF()->GetCharInfo(charCode, charInfo); + font->GetPGF()->GetCharInfo(charCode, charInfo, altCharCode); return 0; } @@ -842,11 +845,13 @@ int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) { DEBUG_LOG(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr); if (!Memory::IsValidAddress(charRectPtr)) return -1; - + PGFCharInfo charInfo; LoadedFont *font = GetLoadedFont(fontHandle, false); + auto fontLib = font->GetFontLib(); + int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode(); if (font) { - font->GetPGF()->GetCharInfo(charCode, &charInfo); + font->GetPGF()->GetCharInfo(charCode, &charInfo, altCharCode); Memory::Write_U16(charInfo.bitmapWidth, charRectPtr); // character bitmap width in pixels Memory::Write_U16(charInfo.bitmapHeight, charRectPtr + 2); // character bitmap height in pixels } else { @@ -874,7 +879,7 @@ int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) { DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr); auto glyph = Memory::GetStruct(glyphImagePtr); int altCharCode = font->GetFontLib()->GetAltCharCode(); - font->GetPGF()->DrawCharacter(glyph, 0, 0, 8192, 8192, charCode, altCharCode, FONT_PGF_CHARGLYPH, packagedFont); + font->GetPGF()->DrawCharacter(glyph, 0, 0, 8192, 8192, charCode, altCharCode, FONT_PGF_CHARGLYPH); return 0; } @@ -892,7 +897,7 @@ int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePt INFO_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight); auto glyph = Memory::GetStruct(glyphImagePtr); int altCharCode = font->GetFontLib()->GetAltCharCode(); - font->GetPGF()->DrawCharacter(glyph, clipXPos, clipYPos, clipXPos + clipWidth, clipYPos + clipHeight, charCode, altCharCode, FONT_PGF_CHARGLYPH, packagedFont); + font->GetPGF()->DrawCharacter(glyph, clipXPos, clipYPos, clipXPos + clipWidth, clipYPos + clipHeight, charCode, altCharCode, FONT_PGF_CHARGLYPH); return 0; } diff --git a/Core/HLE/sceHprm.cpp b/Core/HLE/sceHprm.cpp index a4967be2e7..d8dbb85adc 100644 --- a/Core/HLE/sceHprm.cpp +++ b/Core/HLE/sceHprm.cpp @@ -21,7 +21,7 @@ #include "sceCtrl.h" u32 sceHprmPeekCurrentKey(u32 keyAddress) { - INFO_LOG(HLE,"0=sceHprmPeekCurrentKey(ptr)"); + DEBUG_LOG(HLE,"0=sceHprmPeekCurrentKey(ptr)"); Memory::Write_U32(0, keyAddress); return 0; } diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 93bfe00f2d..675a3204f6 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -360,7 +360,7 @@ void __IoSyncNotify(u64 userdata, int cyclesLate) { if (ioManager.WaitResult(f->handle, managerResult)) { result = managerResult; } else { - ERROR_LOG(SCEIO, "Unable to complete IO operation."); + ERROR_LOG(SCEIO, "Unable to complete IO operation on %s", f->GetName()); } HLEKernel::ResumeFromWait(threadID, WAITTYPE_IO, fd, result); @@ -441,8 +441,6 @@ void __IoWakeManager() { } void __IoInit() { - INFO_LOG(SCEIO, "Starting up I/O..."); - MemoryStick_SetFatState(PSP_FAT_MEMORYSTICK_STATE_ASSIGNED); asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify); @@ -552,16 +550,22 @@ u32 sceIoUnassign(const char *alias) } u32 sceKernelStdin() { + // fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497 + hleEatCycles(1); DEBUG_LOG(SCEIO, "3=sceKernelStdin()"); return 3; } u32 sceKernelStdout() { + // fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497 + hleEatCycles(1); DEBUG_LOG(SCEIO, "1=sceKernelStdout()"); return 1; } u32 sceKernelStderr() { + // fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497 + hleEatCycles(1); DEBUG_LOG(SCEIO, "2=sceKernelStderr()"); return 2; } @@ -1444,7 +1448,6 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, break; case 0x02425823: // Check if FAT enabled - hleEatCycles(23500); // If the values added together are >= 0x80000000, or less than outPtr, invalid address. if (((int)outPtr + outLen) < (int)outPtr) { ERROR_LOG(SCEIO, "sceIoDevctl: fatms0: 0x02425823 command, bad address"); @@ -1456,7 +1459,7 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, } else { // Does not care about outLen, even if it's 0. Memory::Write_U32(MemoryStick_FatState(), outPtr); - return 0; + return hleDelayResult(0, "check fat state", cyclesToUs(23500)); } break; case 0x02425824: @@ -1927,7 +1930,7 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out key_ptr = NULL; } - INFO_LOG(SCEIO, "Decrypting PGD DRM files"); + DEBUG_LOG(SCEIO, "Decrypting PGD DRM files"); pspFileSystem.SeekFile(f->handle, (s32)f->pgd_offset, FILEMOVE_BEGIN); pspFileSystem.ReadFile(f->handle, pgd_header, 0x90); f->pgdInfo = pgd_open(pgd_header, 2, key_ptr); diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index 98ad8c5b81..0dd29226a7 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -315,9 +315,9 @@ int sceJpegInitMJpeg() return 0; } -int sceJpeg_A06A75C4() +int sceJpegMJpegCscWithColorOption() { - ERROR_LOG_REPORT(ME, "UNIMPL sceJpeg_A06A75C4()"); + ERROR_LOG_REPORT(ME, "UNIMPL sceJpegMJpegCscWithColorOption()"); return 0; } @@ -337,7 +337,7 @@ const HLEFunction sceJpeg[] = {0x9B36444C, WrapI_V, "sceJpeg_9B36444C"}, {0x9D47469C, WrapI_II, "sceJpegCreateMJpeg"}, {0xAC9E70E6, WrapI_V, "sceJpegInitMJpeg"}, - {0xa06a75c4, WrapI_V, "sceJpeg_A06A75C4"}, + {0xa06a75c4, WrapI_V, "sceJpegMJpegCscWithColorOption"}, }; void Register_sceJpeg() diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index e242f3e72d..3ee15ed888 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -287,7 +287,7 @@ void sceKernelExitGameWithStatus() u32 sceKernelDevkitVersion() { - int firmwareVersion = 150; + int firmwareVersion = g_Config.iFirmwareVersion; int major = firmwareVersion / 100; int minor = (firmwareVersion / 10) % 10; int revision = firmwareVersion % 10; @@ -590,8 +590,8 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) return __KernelThreadObject(); case SCE_KERNEL_TMID_VTimer: return __KernelVTimerObject(); - case SCE_KERNEL_TMID_Tls: - return __KernelTlsObject(); + case SCE_KERNEL_TMID_Tlspl: + return __KernelTlsplObject(); case PPSSPP_KERNEL_TMID_File: return __KernelFileNodeObject(); case PPSSPP_KERNEL_TMID_DirList: @@ -851,15 +851,14 @@ const HLEFunction ThreadManForUser[] = {0xd8b299ae,WrapU_IUUU, "sceKernelSetVTimerHandler"}, {0x53B00E9A,WrapU_IU64UU, "sceKernelSetVTimerHandlerWide"}, - // Names are just guesses, not correct. - {0x8daff657,WrapI_CUUUUU, "sceKernelCreateTls"}, - {0x32bf938e,WrapI_I, "sceKernelDeleteTls"}, - {0x721067F3,WrapI_IU, "sceKernelReferTlsStatus"}, + {0x8daff657,WrapI_CUUUUU, "sceKernelCreateTlspl"}, + {0x32bf938e,WrapI_I, "sceKernelDeleteTlspl"}, + {0x721067F3,WrapI_IU, "sceKernelReferTlsplStatus"}, // Not completely certain about args. - {0x4A719FB2,WrapI_I, "sceKernelFreeTls"}, - // Probably internal, not sure. Takes (uid, &addr) as parameters... probably. - //{0x65F54FFB,0, "_sceKernelAllocateTls"}, - // NOTE: sceKernelAllocateTls is in Kernel_Library, see sceKernelInterrupt.cpp. + {0x4A719FB2,WrapI_I, "sceKernelFreeTlspl"}, + // Internal. Takes (uid, &addr) as parameters... probably. + //{0x65F54FFB,0, "_sceKernelAllocateTlspl"}, + // NOTE: sceKernelGetTlsAddr is in Kernel_Library, see sceKernelInterrupt.cpp. // Not sure if these should be hooked up. See below. {0x0E927AED, _sceKernelReturnFromTimerHandler, "_sceKernelReturnFromTimerHandler"}, diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 39c61d52c0..75c99ea6a4 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -328,7 +328,7 @@ enum TMIDPurpose SCE_KERNEL_TMID_SuspendThread = 66, SCE_KERNEL_TMID_DormantThread = 67, // No idea what the correct value is here or how to find out. - SCE_KERNEL_TMID_Tls = 0x1001, + SCE_KERNEL_TMID_Tlspl = 0x1001, // Not official, but need ids for save states. PPSSPP_KERNEL_TMID_Module = 0x100001, @@ -451,7 +451,8 @@ public: { if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset]) { - if (handle != 0) + // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP + if (handle != 0 && handle != 0x80020001) { WARN_LOG(SCEKERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 5a1480fa16..a45d2d4a49 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -19,15 +19,16 @@ #include #include -#include "HLE.h" -#include "../MIPS/MIPS.h" -#include "ChunkFile.h" +#include "Core/HLE/HLE.h" +#include "Core/MIPS/MIPS.h" +#include "Common/ChunkFile.h" -#include "sceKernel.h" -#include "sceKernelThread.h" -#include "sceKernelInterrupt.h" -#include "sceKernelMemory.h" -#include "sceKernelMutex.h" +#include "Core/Debugger/Breakpoints.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelInterrupt.h" +#include "Core/HLE/sceKernelMemory.h" +#include "Core/HLE/sceKernelMutex.h" #include "GPU/GPUCommon.h" void __DisableInterrupts(); @@ -580,6 +581,10 @@ u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) *dstp++ = *srcp++; } } +#ifndef USING_GLES2 + CBreakPoints::ExecMemCheck(src, false, size, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dst, true, size, currentMIPS->pc); +#endif return dst; } @@ -600,8 +605,7 @@ const HLEFunction Kernel_Library[] = {0x293b45b8,WrapI_V, "sceKernelGetThreadId"}, {0xD13BDE95,WrapI_V, "sceKernelCheckThreadStack"}, {0x1839852A,WrapU_UUU, "sceKernelMemcpy"}, - // Name is only a guess. - {0xfa835cde,WrapI_I, "sceKernelAllocateTls"}, + {0xfa835cde,WrapI_I, "sceKernelGetTlsAddr"}, }; void Register_Kernel_Library() diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 222f34d05f..868f260717 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -32,7 +32,7 @@ #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/KernelWaitHelpers.h" -const int TLS_NUM_INDEXES = 16; +const int TLSPL_NUM_INDEXES = 16; ////////////////////////////////////////////////////////////////////////// // STATE BEGIN @@ -41,7 +41,7 @@ BlockAllocator kernelMemory(256); static int vplWaitTimer = -1; static int fplWaitTimer = -1; -static bool tlsUsedIndexes[TLS_NUM_INDEXES]; +static bool tlsplUsedIndexes[TLSPL_NUM_INDEXES]; // STATE END ////////////////////////////////////////////////////////////////////////// @@ -218,7 +218,7 @@ void __KernelMemoryInit() flags_ = 0; sdkVersion_ = 0; compilerVersion_ = 0; - memset(tlsUsedIndexes, 0, sizeof(tlsUsedIndexes)); + memset(tlsplUsedIndexes, 0, sizeof(tlsplUsedIndexes)); __KernelRegisterWaitTypeFuncs(WAITTYPE_VPL, __KernelVplBeginCallback, __KernelVplEndCallback); __KernelRegisterWaitTypeFuncs(WAITTYPE_FPL, __KernelFplBeginCallback, __KernelFplEndCallback); @@ -240,16 +240,20 @@ void __KernelMemoryDoState(PointerWrap &p) p.Do(flags_); p.Do(sdkVersion_); p.Do(compilerVersion_); - p.DoArray(tlsUsedIndexes, ARRAY_SIZE(tlsUsedIndexes)); + p.DoArray(tlsplUsedIndexes, ARRAY_SIZE(tlsplUsedIndexes)); } void __KernelMemoryShutdown() { +#ifdef _DEBUG INFO_LOG(SCEKERNEL,"Shutting down user memory pool: "); userMemory.ListBlocks(); +#endif userMemory.Shutdown(); +#ifdef _DEBUG INFO_LOG(SCEKERNEL,"Shutting down \"kernel\" memory pool: "); kernelMemory.ListBlocks(); +#endif kernelMemory.Shutdown(); } @@ -704,7 +708,9 @@ public: address = alloc->AllocAligned(size, 0x100, alignment, type == PSP_SMEM_HighAligned, name); else address = alloc->Alloc(size, type == PSP_SMEM_High, name); +#ifdef _DEBUG alloc->ListBlocks(); +#endif } } ~PartitionMemoryBlock() @@ -1577,20 +1583,20 @@ u32 SysMemUserForUser_D8DE5C1E(){ enum { - PSP_ERROR_UNKNOWN_TLS_ID = 0x800201D0, - PSP_ERROR_TOO_MANY_TLS = 0x800201D1, + PSP_ERROR_UNKNOWN_TLSPL_ID = 0x800201D0, + PSP_ERROR_TOO_MANY_TLSPL = 0x800201D1, }; enum { // TODO: Complete untested guesses. - PSP_TLS_ATTR_FIFO = 0, - PSP_TLS_ATTR_PRIORITY = 0x100, - PSP_TLS_ATTR_HIGHMEM = 0x4000, - PSP_TLS_ATTR_KNOWN = PSP_TLS_ATTR_HIGHMEM | PSP_TLS_ATTR_PRIORITY | PSP_TLS_ATTR_FIFO, + PSP_TLSPL_ATTR_FIFO = 0, + PSP_TLSPL_ATTR_PRIORITY = 0x100, + PSP_TLSPL_ATTR_HIGHMEM = 0x4000, + PSP_TLSPL_ATTR_KNOWN = PSP_TLSPL_ATTR_HIGHMEM | PSP_TLSPL_ATTR_PRIORITY | PSP_TLSPL_ATTR_FIFO, }; -struct NativeTls +struct NativeTlspl { SceSize_le size; char name[32]; @@ -1602,15 +1608,15 @@ struct NativeTls u32_le numWaitThreads; }; -struct TLS : public KernelObject +struct TLSPL : public KernelObject { const char *GetName() {return ntls.name;} const char *GetTypeName() {return "TLS";} - static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLS_ID; } - static int GetStaticIDType() { return SCE_KERNEL_TMID_Tls; } - int GetIDType() const { return SCE_KERNEL_TMID_Tls; } + static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLSPL_ID; } + static int GetStaticIDType() { return SCE_KERNEL_TMID_Tlspl; } + int GetIDType() const { return SCE_KERNEL_TMID_Tlspl; } - TLS() : next(0) {} + TLSPL() : next(0) {} virtual void DoState(PointerWrap &p) { @@ -1625,39 +1631,39 @@ struct TLS : public KernelObject p.Do(usage); } - NativeTls ntls; + NativeTlspl ntls; u32 address; std::vector waitingThreads; int next; std::vector usage; }; -KernelObject *__KernelTlsObject() +KernelObject *__KernelTlsplObject() { - return new TLS; + return new TLSPL; } -SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSize, u32 count, u32 optionsPtr) +SceUID sceKernelCreateTlspl(const char *name, u32 partition, u32 attr, u32 blockSize, u32 count, u32 optionsPtr) { if (!name) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY); + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY); return SCE_KERNEL_ERROR_NO_MEMORY; } - if ((attr & ~PSP_TLS_ATTR_KNOWN) >= 0x100) + if ((attr & ~PSP_TLSPL_ATTR_KNOWN) >= 0x100) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr); + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr); return SCE_KERNEL_ERROR_ILLEGAL_ATTR; } if (partition < 1 || partition > 9 || partition == 7) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition); + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition); return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } // We only support user right now. if (partition != 2 && partition != 6) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition); + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition); return SCE_KERNEL_ERROR_ILLEGAL_PERM; } @@ -1670,13 +1676,13 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi illegalMemSize = true; if (illegalMemSize) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE); + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE); return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE; } int index = -1; - for (int i = 0; i < TLS_NUM_INDEXES; ++i) - if (tlsUsedIndexes[i] == false) + for (int i = 0; i < TLSPL_NUM_INDEXES; ++i) + if (tlsplUsedIndexes[i] == false) { index = i; break; @@ -1684,21 +1690,23 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi if (index == -1) { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): ran out of indexes for TLS objects", PSP_ERROR_TOO_MANY_TLS); - return PSP_ERROR_TOO_MANY_TLS; + WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): ran out of indexes for TLS pools", PSP_ERROR_TOO_MANY_TLSPL); + return PSP_ERROR_TOO_MANY_TLSPL; } u32 totalSize = blockSize * count; - u32 blockPtr = userMemory.Alloc(totalSize, (attr & PSP_TLS_ATTR_HIGHMEM) != 0, name); + u32 blockPtr = userMemory.Alloc(totalSize, (attr & PSP_TLSPL_ATTR_HIGHMEM) != 0, name); +#ifdef _DEBUG userMemory.ListBlocks(); +#endif if (blockPtr == (u32) -1) { - ERROR_LOG(SCEKERNEL, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x): failed to allocate memory", SCE_KERNEL_ERROR_NO_MEMORY, name, partition, attr, blockSize, count, optionsPtr); + ERROR_LOG(SCEKERNEL, "%08x=sceKernelCreateTlspl(%s, %d, %08x, %d, %d, %08x): failed to allocate memory", SCE_KERNEL_ERROR_NO_MEMORY, name, partition, attr, blockSize, count, optionsPtr); return SCE_KERNEL_ERROR_NO_MEMORY; } - TLS *tls = new TLS(); + TLSPL *tls = new TLSPL(); SceUID id = kernelObjects.Create(tls); tls->ntls.size = sizeof(tls->ntls); @@ -1706,7 +1714,7 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi tls->ntls.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; tls->ntls.attr = attr; tls->ntls.index = index; - tlsUsedIndexes[index] = true; + tlsplUsedIndexes[index] = true; tls->ntls.blockSize = blockSize; tls->ntls.totalBlocks = count; tls->ntls.freeBlocks = count; @@ -1714,47 +1722,47 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi tls->address = blockPtr; tls->usage.resize(count, 0); - WARN_LOG(SCEKERNEL, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x)", id, name, partition, attr, blockSize, count, optionsPtr); + WARN_LOG(SCEKERNEL, "%08x=sceKernelCreateTlspl(%s, %d, %08x, %d, %d, %08x)", id, name, partition, attr, blockSize, count, optionsPtr); // TODO: just alignment? if (optionsPtr != 0) { u32 size = Memory::Read_U32(optionsPtr); if (size > 4) - WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTls(%s) unsupported options parameter, size = %d", name, size); + WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTlspl(%s) unsupported options parameter, size = %d", name, size); } - if ((attr & PSP_TLS_ATTR_PRIORITY) != 0) - WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTls(%s) unsupported attr parameter: %08x", name, attr); + if ((attr & PSP_TLSPL_ATTR_PRIORITY) != 0) + WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTlspl(%s) unsupported attr parameter: %08x", name, attr); return id; } // Parameters are an educated guess. -int sceKernelDeleteTls(SceUID uid) +int sceKernelDeleteTlspl(SceUID uid) { - WARN_LOG(SCEKERNEL, "sceKernelDeleteTls(%08x)", uid); + WARN_LOG(SCEKERNEL, "sceKernelDeleteTlspl(%08x)", uid); u32 error; - TLS *tls = kernelObjects.Get(uid, error); + TLSPL *tls = kernelObjects.Get(uid, error); if (tls) { // TODO: Wake waiting threads, probably? userMemory.Free(tls->address); - tlsUsedIndexes[tls->ntls.index] = false; - kernelObjects.Destroy(uid); + tlsplUsedIndexes[tls->ntls.index] = false; + kernelObjects.Destroy(uid); } return error; } -int sceKernelAllocateTls(SceUID uid) +int sceKernelGetTlsAddr(SceUID uid) { - // TODO: Allocate downward if PSP_TLS_ATTR_HIGHMEM? - DEBUG_LOG(SCEKERNEL, "sceKernelAllocateTls(%08x)", uid); + // TODO: Allocate downward if PSP_TLSPL_ATTR_HIGHMEM? + DEBUG_LOG(SCEKERNEL, "sceKernelGetTlsAddr(%08x)", uid); if (!__KernelIsDispatchEnabled() || __IsInInterrupt()) return 0; u32 error; - TLS *tls = kernelObjects.Get(uid, error); + TLSPL *tls = kernelObjects.Get(uid, error); if (tls) { SceUID threadID = __KernelGetCurThread(); @@ -1787,7 +1795,7 @@ int sceKernelAllocateTls(SceUID uid) if (allocBlock == -1) { tls->waitingThreads.push_back(threadID); - __KernelWaitCurThread(WAITTYPE_TLS, uid, 1, 0, false, "allocate tls"); + __KernelWaitCurThread(WAITTYPE_TLSPL, uid, 1, 0, false, "allocate tls"); return -1; } @@ -1798,11 +1806,11 @@ int sceKernelAllocateTls(SceUID uid) } // Parameters are an educated guess. -int sceKernelFreeTls(SceUID uid) +int sceKernelFreeTlspl(SceUID uid) { - WARN_LOG(SCEKERNEL, "UNIMPL sceKernelFreeTls(%08x)", uid); + WARN_LOG(SCEKERNEL, "UNIMPL sceKernelFreeTlspl(%08x)", uid); u32 error; - TLS *tls = kernelObjects.Get(uid, error); + TLSPL *tls = kernelObjects.Get(uid, error); if (tls) { SceUID threadID = __KernelGetCurThread(); @@ -1827,7 +1835,7 @@ int sceKernelFreeTls(SceUID uid) tls->waitingThreads.erase(tls->waitingThreads.begin()); // This thread must've been woken up. - if (!HLEKernel::VerifyWait(waitingThreadID, WAITTYPE_TLS, uid)) + if (!HLEKernel::VerifyWait(waitingThreadID, WAITTYPE_TLSPL, uid)) continue; // Otherwise, if there was a thread waiting, we were full, so this newly freed one is theirs. @@ -1852,11 +1860,11 @@ int sceKernelFreeTls(SceUID uid) } // Parameters are an educated guess. -int sceKernelReferTlsStatus(SceUID uid, u32 infoPtr) +int sceKernelReferTlsplStatus(SceUID uid, u32 infoPtr) { - DEBUG_LOG(SCEKERNEL, "sceKernelReferTlsStatus(%08x, %08x)", uid, infoPtr); + DEBUG_LOG(SCEKERNEL, "sceKernelReferTlsplStatus(%08x, %08x)", uid, infoPtr); u32 error; - TLS *tls = kernelObjects.Get(uid, error); + TLSPL *tls = kernelObjects.Get(uid, error); if (tls) { // TODO: Check size. diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index d9ab052f46..b19e592578 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -35,7 +35,7 @@ void __KernelMemoryShutdown(); KernelObject *__KernelMemoryFPLObject(); KernelObject *__KernelMemoryVPLObject(); KernelObject *__KernelMemoryPMBObject(); -KernelObject *__KernelTlsObject(); +KernelObject *__KernelTlsplObject(); SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize, u32 optPtr); int sceKernelDeleteVpl(SceUID uid); @@ -57,10 +57,10 @@ int sceKernelReferFplStatus(SceUID uid, u32 statusPtr); int sceKernelGetCompiledSdkVersion(); -SceUID sceKernelCreateTls(const char *name, u32 partitionid, u32 attr, u32 size, u32 count, u32 optionsPtr); -int sceKernelDeleteTls(SceUID uid); -int sceKernelAllocateTls(SceUID uid); -int sceKernelFreeTls(SceUID uid); -int sceKernelReferTlsStatus(SceUID uid, u32 infoPtr); +SceUID sceKernelCreateTlspl(const char *name, u32 partitionid, u32 attr, u32 size, u32 count, u32 optionsPtr); +int sceKernelDeleteTlspl(SceUID uid); +int sceKernelGetTlsAddr(SceUID uid); +int sceKernelFreeTlspl(SceUID uid); +int sceKernelReferTlsplStatus(SceUID uid, u32 infoPtr); void Register_SysMemUserForUser(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 867cecb90b..acd14ade12 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -47,6 +47,8 @@ #include "Core/HLE/sceIo.h" #include "Core/HLE/KernelWaitHelpers.h" +#include "GPU/GPUState.h" + enum { PSP_THREAD_ATTR_USER = 0x80000000 }; @@ -175,6 +177,7 @@ struct NativeModule { // by QueryModuleInfo struct ModuleInfo { + SceSize_le size; u32_le nsegment; u32_le segmentaddr[4]; u32_le segmentsize[4]; @@ -257,7 +260,7 @@ public: // Add the symbol to the symbol map for debugging. char temp[256]; sprintf(temp,"zz_%s", GetFuncName(func.moduleName, func.nid)); - symbolMap.AddSymbol(temp, func.stubAddr, 8, ST_FUNCTION); + symbolMap.AddFunction(temp,func.stubAddr,8); // Keep track and actually hook it up if possible. importedFuncs.push_back(func); @@ -496,6 +499,7 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type, bool reverse = // We add 1 in that case so that it ends up the right value. u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0); Memory::Write_U32((it->data & ~0xFFFF) | high, it->addr); + currentMIPS->InvalidateICache(it->addr, 4); } lastHI16Processed = true; } @@ -692,7 +696,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } *magic = *magicPtr; if (*magic == 0x5053507e) { // "~PSP" - INFO_LOG(SCEMODULE, "Decrypting ~PSP file"); + DEBUG_LOG(SCEMODULE, "Decrypting ~PSP file"); PSP_Header *head = (PSP_Header*)ptr; const u8 *in = ptr; u32 size = head->elf_size; @@ -714,12 +718,13 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro module->nm.entry_addr = -1; module->nm.gp_value = -1; return module; - } - else if (ret <= 0) - { + } else if (ret <= 0) { ERROR_LOG(SCEMODULE, "Failed decrypting PRX! That's not normal! ret = %i\n", ret); Reporting::ReportMessage("Failed decrypting the PRX (ret = %i, size = %i, psp_size = %i)!", ret, head->elf_size, head->psp_size); // Fall through to safe exit in the next check. + } else { + // TODO: Is this right? + module->nm.bss_size = head->bss_size; } } @@ -769,6 +774,15 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro else modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSegmentVaddr(0) + (reader.GetSegmentPaddr(0) & 0x7FFFFFFF) - reader.GetSegmentOffset(0)); + module->nm.nsegment = reader.GetNumSegments(); + module->nm.attribute = modinfo->moduleAttrs; + module->nm.version[0] = modinfo->moduleVersion & 0xFF; + module->nm.version[1] = modinfo->moduleVersion >> 8; + module->nm.data_size = 0; + // TODO: Is summing them up correct? Must not be since the numbers aren't exactly right. + for (int i = 0; i < reader.GetNumSegments(); ++i) { + module->nm.data_size += reader.GetSegmentDataSize(i); + } module->nm.gp_value = modinfo->gp; strncpy(module->nm.name, modinfo->name, 28); @@ -794,6 +808,12 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro u32 textStart = reader.GetSectionAddr(textSection); u32 textSize = reader.GetSectionSize(textSection); + module->nm.text_addr = textStart; + // TODO: This value appears to be wrong. In one example, the PSP has a value > 0x1000 bigger. + module->nm.text_size = textSize; + // TODO: It seems like the data size excludes the text size, which kinda makes sense? + module->nm.data_size -= textSize; + #if !defined(USING_GLES2) if (!reader.LoadSymbols()) MIPSAnalyst::ScanForFunctions(textStart, textStart+textSize); @@ -836,6 +856,8 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro u32_le *entryPos = (u32_le *)Memory::GetPointer(modinfo->libstub); u32_le *entryEnd = (u32_le *)Memory::GetPointer(modinfo->libstubend); + u32_le firstImportStubAddr = 0; + bool needReport = false; while (entryPos < entryEnd) { PspLibStubEntry *entry = (PspLibStubEntry *)entryPos; @@ -880,6 +902,9 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro func.stubAddr = entry->firstSymAddr + i * 8; module->ImportFunc(func); } + + if (!firstImportStubAddr || firstImportStubAddr > entry->firstSymAddr) + firstImportStubAddr = entry->firstSymAddr; } else if (entry->numFuncs > 0) { WARN_LOG_REPORT(LOADER, "Module entry with %d imports but no valid address", entry->numFuncs); needReport = true; @@ -943,6 +968,15 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro Reporting::ReportMessage("Module linking debug info:\n%s", debugInfo.c_str()); } + if (textSection == -1) { + u32 textStart = reader.GetVaddr(); + u32 textEnd = firstImportStubAddr - 4; +#if !defined(USING_GLES2) + if (!reader.LoadSymbols()) + MIPSAnalyst::ScanForFunctions(textStart, textEnd); +#endif + } + // Look at the exports, too. struct PspLibEntEntry @@ -1139,7 +1173,22 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string for (int i = 1; i < numfiles; i++) memcpy(&offsets[i], fileptr + 12 + 4*i, 4); u32 magic = 0; - module = __KernelLoadELFFromPtr(fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic); + + + u8 *temp = 0; + if (offsets[5] & 3) { + // Our loader does NOT like to load from an unaligned address on ARM! + size_t size = offsets[6] - offsets[5]; + temp = new u8[size]; + memcpy(temp, fileptr + offsets[5], size); + INFO_LOG(LOADER, "Elf unaligned, aligning!") + } + + module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic); + + if (temp) { + delete [] temp; + } } else { @@ -1208,6 +1257,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str //HLE needs to be reset here HLEShutdown(); HLEInit(); + GPU_Reinitialize(); } __KernelModuleInit(); @@ -1752,21 +1802,53 @@ u32 sceKernelQueryModuleInfo(u32 uid, u32 infoAddr) ERROR_LOG(SCEMODULE, "sceKernelQueryModuleInfo(%i, %08x) - bad infoAddr", uid, infoAddr); return -1; } - ModuleInfo info; - memcpy(info.segmentaddr, module->nm.segmentaddr, sizeof(info.segmentaddr)); - memcpy(info.segmentsize, module->nm.segmentsize, sizeof(info.segmentsize)); - info.nsegment = module->nm.nsegment; - info.entry_addr = module->nm.entry_addr; - info.gp_value = module->nm.gp_value; - info.text_addr = module->nm.text_addr; - info.text_size = module->nm.text_size; - info.data_size = module->nm.data_size; - info.bss_size = module->nm.bss_size; - info.attribute = module->nm.attribute; - info.version[0] = module->nm.version[0]; - info.version[1] = module->nm.version[1]; - memcpy(info.name, module->nm.name, 28); - Memory::WriteStruct(infoAddr, &info); + + PSPPointer info; + info = infoAddr; + + memcpy(info->segmentaddr, module->nm.segmentaddr, sizeof(info->segmentaddr)); + memcpy(info->segmentsize, module->nm.segmentsize, sizeof(info->segmentsize)); + info->nsegment = module->nm.nsegment; + info->entry_addr = module->nm.entry_addr; + info->gp_value = module->nm.gp_value; + info->text_addr = module->nm.text_addr; + info->text_size = module->nm.text_size; + info->data_size = module->nm.data_size; + info->bss_size = module->nm.bss_size; + + // Even if it's bigger, if it's not exactly 96, skip this extra data. + // Even if it's 0, the above are all written though. + if (info->size == 96) { + info->attribute = module->nm.attribute; + info->version[0] = module->nm.version[0]; + info->version[1] = module->nm.version[1]; + memcpy(info->name, module->nm.name, 28); + } + + return 0; +} + +u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 idCountAddr) +{ + ERROR_LOG(SCEMODULE, "UNTESTED sceKernelGetModuleIdList(%08x, %i, %08x)", resultBuffer, resultBufferSize, idCountAddr); + + int idCount = 0; + u32 resultBufferOffset = 0; + + u32 error; + for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) { + Module *module = kernelObjects.Get(*mod, error); + if (!module->isFake) { + if (resultBufferOffset < (int)resultBufferSize) { + Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset); + resultBufferOffset += 4; + } + idCount++; + } + } + + Memory::Write_U32(idCount, idCountAddr); + return 0; } @@ -1805,7 +1887,7 @@ const HLEFunction ModuleMgrForUser[] = {0xf0a26395,WrapU_V, "sceKernelGetModuleId"}, {0x8f2df740,WrapU_UUUUU,"sceKernelStopUnloadSelfModuleWithStatus"}, {0xfef27dc1,&WrapU_CU , "sceKernelLoadModuleDNAS"}, - {0x644395e2,0,"sceKernelGetModuleIdList"}, + {0x644395e2,WrapU_UUU,"sceKernelGetModuleIdList"}, {0xf2d8d1b4,&WrapU_CUU,"sceKernelLoadModuleNpDrm"}, {0xe4c4211c,0,"ModuleMgrForUser_E4C4211C"}, {0xfbe27467,0,"ModuleMgrForUser_FBE27467"}, diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index a2dcc48858..03ff9621e9 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -68,7 +68,7 @@ const WaitTypeNames waitTypeNames[] = { { WAITTYPE_GELISTSYNC, "GeListSync" }, { WAITTYPE_MODULE, "Module" }, { WAITTYPE_HLEDELAY, "HleDelay" }, - { WAITTYPE_TLS, "TLS" }, + { WAITTYPE_TLSPL, "TLS" }, { WAITTYPE_VMEM, "Volatile Mem" }, { WAITTYPE_ASYNCIO, "AsyncIO" }, }; @@ -520,7 +520,7 @@ public: virtual void DoState(PointerWrap &p) { - auto s = p.Section("Thread", 1, 2); + auto s = p.Section("Thread", 1, 4); if (!s) return; @@ -530,8 +530,27 @@ public: p.Do(isProcessingCallbacks); p.Do(currentMipscallId); p.Do(currentCallbackId); + + // TODO: How do I "version" adding a DoState method to ThreadContext? p.Do(context); + if (s <= 3) + { + // We must have been loading an old state if we're here. + // Reorder VFPU data to new order. + float temp[128]; + memcpy(temp, context.v, 128 * sizeof(float)); + for (int i = 0; i < 128; i++) { + context.v[voffset[i]] = temp[i]; + } + } + + if (s <= 2) + { + context.other[4] = context.other[5]; + context.other[3] = context.other[4]; + } + p.Do(callbacks); p.Do(pendingMipsCalls); @@ -1928,8 +1947,7 @@ void ThreadContext::reset() vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; fpcond = 0; - fcr0 = 0; - fcr31 = 0; + fcr31 = 0x00000e00; hi = 0xDEADBEEF; lo = 0xDEADBEEF; } @@ -2328,10 +2346,9 @@ int sceKernelRotateThreadReadyQueue(int priority) // Yield the next thread of this priority to all other threads of same priority. else threadReadyQueue.rotate(priority); - - hleReSchedule("rotatethreadreadyqueue"); } + hleReSchedule("rotatethreadreadyqueue"); hleEatCycles(250); return 0; } @@ -2515,6 +2532,7 @@ int sceKernelChangeThreadPriority(SceUID threadID, int priority) if (thread->isReady()) threadReadyQueue.push_back(thread->nt.currentPriority, threadID); + hleEatCycles(450); hleReSchedule("change thread priority"); return 0; } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 4562509f70..b77ff005f9 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -92,7 +92,7 @@ enum WaitType WAITTYPE_GELISTSYNC = 18, WAITTYPE_MODULE = 19, WAITTYPE_HLEDELAY = 20, - WAITTYPE_TLS = 21, + WAITTYPE_TLSPL = 21, WAITTYPE_VMEM = 22, WAITTYPE_ASYNCIO = 23, @@ -132,7 +132,6 @@ struct ThreadContext u32 hi; u32 lo; - u32 fcr0; u32 fcr31; u32 fpcond; }; diff --git a/Core/HLE/sceKernelTime.cpp b/Core/HLE/sceKernelTime.cpp index c57c3c3394..6eb88b2fcf 100644 --- a/Core/HLE/sceKernelTime.cpp +++ b/Core/HLE/sceKernelTime.cpp @@ -71,7 +71,7 @@ u32 sceKernelGetSystemTimeLow() u64 sceKernelGetSystemTimeWide() { - u64 t = CoreTiming::GetGlobalTimeUs(); + u64 t = CoreTiming::GetGlobalTimeUsScaled(); DEBUG_LOG(SCEKERNEL,"%i=sceKernelGetSystemTimeWide()",(u32)t); hleEatCycles(250); hleReSchedule("system time"); diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index ef2e08c4fc..39c2fa70ca 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -612,8 +612,8 @@ u32 sceMp3GetFrameNum(u32 mp3) { return 0; } -u32 sceMp3GetVersion(u32 mp3) { - DEBUG_LOG(ME, "sceMp3GetVersion(%08x)", mp3); +u32 sceMp3GetMPEGVersion(u32 mp3) { + DEBUG_LOG(ME, "sceMp3GetMPEGVersion(%08x)", mp3); Mp3Context *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); @@ -623,8 +623,8 @@ u32 sceMp3GetVersion(u32 mp3) { return ctx->mp3Version; } -u32 sceMp3ResetPlayPosition2(u32 mp3, int position) { - DEBUG_LOG(ME, "sceMp3ResetPlayPosition2(%08x, %i)", mp3, position); +u32 sceMp3ResetPlayPositionByFrame(u32 mp3, int position) { + DEBUG_LOG(ME, "sceMp3ResetPlayPositionByFrame(%08x, %i)", mp3, position); Mp3Context *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); @@ -635,13 +635,13 @@ u32 sceMp3ResetPlayPosition2(u32 mp3, int position) { return 0; } -u32 sceMp3_1B839B83() { - ERROR_LOG_REPORT(ME, "UNIMPL sceMp3_1B839B83(...)"); +u32 sceMp3LowLevelInit() { + ERROR_LOG_REPORT(ME, "UNIMPL sceMp3LowLevelInit(...)"); return 0; } -u32 sceMp3_E3EE2C81() { - ERROR_LOG_REPORT(ME, "UNIMPL sceMp3_E3EE2C81(...)"); +u32 sceMp3LowLevelDecode() { + ERROR_LOG_REPORT(ME, "UNIMPL sceMp3LowLevelDecode(...)"); return 0; } @@ -665,11 +665,11 @@ const HLEFunction sceMp3[] = { {0xD0A56296,WrapI_U,"sceMp3CheckStreamDataNeeded"}, {0xD8F54A51,WrapI_U,"sceMp3GetLoopNum"}, {0xF5478233,WrapI_U,"sceMp3ReleaseMp3Handle"}, - {0xAE6D2027,WrapU_U,"sceMp3GetVersion"}, // Incorrect function name + {0xAE6D2027,WrapU_U,"sceMp3GetMPEGVersion"}, {0x3548AEC8,WrapU_U,"sceMp3GetFrameNum"}, - {0x0840e808,WrapU_UI,"sceMp3ResetPlayPosition2"}, // Incorrect function name - {0x1b839b83,WrapU_V,"sceMp3_1B839B83"}, - {0xe3ee2c81,WrapU_V,"sceMp3_E3EE2C81"} + {0x0840e808,WrapU_UI,"sceMp3ResetPlayPositionByFrame"}, + {0x1b839b83,WrapU_V,"sceMp3LowLevelInit"}, + {0xe3ee2c81,WrapU_V,"sceMp3LowLevelDecode"} }; void Register_sceMp3() { diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 5b0e0cc25e..dd4ccad48d 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -668,7 +668,7 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i DEBUG_LOG(ME, "*buffer = %08x, *init = %08x", buffer, init); if (ctx->mediaengine->stepVideo(ctx->videoPixelMode)) { - int bufferSize = ctx->mediaengine->writeVideoImage(Memory::GetPointer(buffer), frameWidth, ctx->videoPixelMode); + int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode); gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE); ctx->avc.avcFrameStatus = 1; ctx->videoFrameCount++; @@ -915,7 +915,13 @@ int sceMpegRingbufferAvailableSize(u32 ringbufferAddr) } hleEatCycles(2020); - DEBUG_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr); + static int lastFree = 0; + if (lastFree != ringbuffer->packetsFree) { + DEBUG_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr); + lastFree = ringbuffer->packetsFree; + } else { + VERBOSE_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr); + } return ringbuffer->packetsFree; } @@ -1256,7 +1262,7 @@ u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init) avcAu.read(auAddr); Memory::Memset(bufferAddr, 0, MPEG_ATRAC_ES_OUTPUT_SIZE); - ctx->mediaengine->getAudioSamples(Memory::GetPointer(bufferAddr)); + ctx->mediaengine->getAudioSamples(bufferAddr); avcAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp; avcAu.write(auAddr); @@ -1280,7 +1286,7 @@ u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth, u32 d int y = Memory::Read_U32(rangeAddr + 4); int width = Memory::Read_U32(rangeAddr + 8); int height = Memory::Read_U32(rangeAddr + 12); - int destSize = ctx->mediaengine->writeVideoImageWithRange(Memory::GetPointer(destAddr), frameWidth, ctx->videoPixelMode, + int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode, x, y, width, height); gpu->InvalidateCache(destAddr, destSize, GPU_INVALIDATE_SAFE); diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 80b963d169..85d68d8d4c 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -15,17 +15,19 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "net/resolve.h" +#include "util/text/parsers.h" + #include "Common/ChunkFile.h" -#include "HLE.h" -#include "../MIPS/MIPS.h" +#include "Core/HLE/HLE.h" +#include "Core/MIPS/MIPS.h" +#include "Core/Config.h" #include "sceKernel.h" #include "sceKernelThread.h" #include "sceKernelMutex.h" #include "sceUtility.h" -#include "net/resolve.h" - static bool netInited; static bool netInetInited; static bool netApctlInited; @@ -130,22 +132,29 @@ u32 sceNetTerm() { } u32 sceWlanGetEtherAddr(u32 addrAddr) { - static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 6 }; + // Read MAC Address from config + uint8_t mac[6] = {0}; + if (!ParseMacAddress(g_Config.localMacAddress.c_str(), mac)) { + ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.localMacAddress.c_str()); + } DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr); for (int i = 0; i < 6; i++) - Memory::Write_U8(fakeEtherAddr[i], addrAddr + i); - + Memory::Write_U8(mac[i], addrAddr + i); return 0; } +u32 sceNetGetLocalEtherAddr(u32 addrAddr) { + return sceWlanGetEtherAddr(addrAddr); +} + u32 sceWlanDevIsPowerOn() { - DEBUG_LOG(SCENET, "UNTESTED 0=sceWlanDevIsPowerOn()"); - return 0; + DEBUG_LOG(SCENET, "UNTESTED sceWlanDevIsPowerOn()"); + return g_Config.bEnableWlan ? 1 : 0; } u32 sceWlanGetSwitchState() { DEBUG_LOG(SCENET, "UNTESTED sceWlanGetSwitchState()"); - return 0; + return g_Config.bEnableWlan ? 1 : 0; } // Probably a void function, but often returns a useful value. @@ -348,7 +357,7 @@ const HLEFunction sceNet[] = { {0x281928A9, WrapU_V, "sceNetTerm"}, {0x89360950, WrapI_UU, "sceNetEtherNtostr"}, {0xd27961c9, WrapI_UU, "sceNetEtherStrton"}, - {0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"}, + {0x0bf0a3ae, WrapU_U, "sceNetGetLocalEtherAddr"}, {0x50647530, 0, "sceNetFreeThreadinfo"}, {0xcc393e48, WrapI_U, "sceNetGetMallocStat"}, {0xad6844c6, 0, "sceNetThreadAbort"}, @@ -385,7 +394,7 @@ const HLEFunction sceNetInet[] = { {0xcda85c99, WrapI_IUUU, "sceNetInetRecv"}, {0xc91142e4, 0, "sceNetInetRecvfrom"}, {0xeece61d2, 0, "sceNetInetRecvmsg"}, - {0x7aa671bc, WrapI_IUUU, "sceNetInetSend"}, + {0x7aa671bc, WrapI_IUUU, "sceNetInetSend"}, {0x05038fc7, 0, "sceNetInetSendto"}, {0x774e36f4, 0, "sceNetInetSendmsg"}, {0xfbabe411, WrapI_V, "sceNetInetGetErrno"}, diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 852b29b6d3..9cc5f3ef41 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -18,31 +18,14 @@ // sceNetAdhoc -// These acronyms are seen in function names: -// * PDP: a proprietary Sony protocol similar to UDP. -// * PTP: a proprietary Sony protocol similar to TCP. - -// We will need to wrap them into the similar UDP and TCP messages. If we want to -// play adhoc remotely online, I guess we'll need to wrap both into TCP/IP. - -// We will need some server infrastructure to provide match making. We'll -// group players per game. Maybe allow players to join rooms and then start the game, -// instead of the other way around? - - -#include "Core/HLE/HLE.h" -#include "Core/HLE/sceNetAdhoc.h" - -#include "sceKernel.h" -#include "sceKernelThread.h" -#include "sceKernelMutex.h" -#include "sceUtility.h" - -#include "net/resolve.h" +// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/ +// All credit goes to him! +#include "proAdhoc.h" enum { ERROR_NET_ADHOC_INVALID_SOCKET_ID = 0x80410701, ERROR_NET_ADHOC_INVALID_ADDR = 0x80410702, + ERROR_NET_ADHOC_INVALID_ARG = 0x80410B04, ERROR_NET_ADHOC_NO_DATA_AVAILABLE = 0x80410709, ERROR_NET_ADHOC_PORT_IN_USE = 0x8041070a, ERROR_NET_ADHOC_NOT_INITIALIZED = 0x80410712, @@ -54,13 +37,45 @@ enum { ERROR_NET_ADHOC_INVALID_MATCHING_ID = 0x80410807, ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED = 0x80410812, ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED = 0x80410813, + ERROR_NET_ADHOC_WOULD_BLOCK = 0x80410709, + ERROR_NET_ADHOC_INVALID_DATALEN = 0x80410705, + ERROR_NET_ADHOC_INVALID_PORT = 0x80410703, + ERROR_NET_ADHOC_NOT_LISTENED = 0x8040070E, + ERROR_NET_ADHOC_NOT_OPENED = 0x8040070D, + ERROR_NET_ADHOC_SOCKET_ID_NOT_AVAIL = 0x8041070F, + ERROR_NET_ADHOC_NOT_CONNECTED = 0x8041070B, + ERROR_NET_ADHOCCTL_INVALID_ARG = 0x80410B04, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF = 0x80410b03, ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED = 0x80410b07, ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, ERROR_NET_ADHOCCTL_DISCONNECTED = 0x80410b09, ERROR_NET_ADHOCCTL_BUSY = 0x80410b10, - ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, + ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, + + ERROR_NET_ADHOC_MATCHING_INVALID_MODE = 0x80410801, + ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM = 0x80410803, + ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT = 0x80410804, + ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN = 0x80410805, + ERROR_NET_ADHOC_MATCHING_INVALID_ARG = 0x80410806, + ERROR_NET_ADHOC_MATCHING_INVALID_ID = 0x80410807, + ERROR_NET_ADHOC_MATCHING_ID_NOT_AVAIL = 0x80410808, + ERROR_NET_ADHOC_MATCHING_NO_SPACE = 0x80410809, + ERROR_NET_ADHOC_MATCHING_IS_RUNNING = 0x8041080A, + ERROR_NET_ADHOC_MATCHING_NOT_RUNNING = 0x8041080B, + ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET = 0x8041080C, + ERROR_NET_ADHOC_MATCHING_TARGET_NOT_READY = 0x8041080D, + ERROR_NET_ADHOC_MATCHING_EXCEED_MAXNUM = 0x8041080E, + ERROR_NET_ADHOC_MATCHING_REQUEST_IN_PROGRESS = 0x8041080F, + ERROR_NET_ADHOC_MATCHING_ALREADY_ESTABLISHED = 0x80410810, + ERROR_NET_ADHOC_MATCHING_BUSY = 0x80410811, + ERROR_NET_ADHOC_MATCHING_PORT_IN_USE = 0x80410814, + ERROR_NET_ADHOC_MATCHING_STACKSIZE_TOO_SHORT = 0x80410815, + ERROR_NET_ADHOC_MATCHING_INVALID_DATALEN = 0x80410816, + ERROR_NET_ADHOC_MATCHING_NOT_ESTABLISHED = 0x80410817, + ERROR_NET_ADHOC_MATCHING_DATA_BUSY = 0x80410818, + + ERROR_NET_NO_SPACE = 0x80410001 }; enum { @@ -76,14 +91,6 @@ static bool netAdhocInited; static bool netAdhocctlInited; static bool netAdhocMatchingInited; -// These might come in handy in the future, if PPSSPP ever supports wifi/ad-hoc.. -struct SceNetAdhocctlParams { - s32_le channel; //which ad-hoc channel to connect to - char name[8]; //connection name - u8 bssid[6]; //BSSID of the connection? - char nickname[128]; //PSP's nickname? -}; - struct AdhocctlHandler { u32 entryPoint; u32 argument; @@ -92,14 +99,30 @@ struct AdhocctlHandler { static std::map adhocctlHandlers; void __NetAdhocInit() { + friendFinderRunning = false; + eventHandlerUpdate = -1; netAdhocInited = false; netAdhocctlInited = false; netAdhocMatchingInited = false; adhocctlHandlers.clear(); } -void __NetAdhocShutdown() { +int sceNetAdhocTerm(); +int sceNetAdhocctlTerm(); +int sceNetAdhocMatchingTerm(); + +void __NetAdhocShutdown() { + // Checks to avoid confusing logspam + if (netAdhocInited) { + sceNetAdhocTerm(); + } + if (netAdhocctlInited) { + sceNetAdhocctlTerm(); + } + if (netAdhocMatchingInited) { + sceNetAdhocMatchingTerm(); + } } void __NetAdhocDoState(PointerWrap &p) { @@ -120,79 +143,478 @@ void __UpdateAdhocctlHandlers(int flag, int error) { for (std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) { args[2] = it->second.argument; - __KernelDirectMipsCall(it->second.entryPoint, NULL, args, 3, true); } } -u32 sceNetAdhocInit() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocInit()"); - if (netAdhocInited) - return ERROR_NET_ADHOC_ALREADY_INITIALIZED; - netAdhocInited = true; - +int getBlockingFlag(int id) { +#ifdef _MSC_VER return 0; +#else + int sockflag = fcntl(id, F_GETFL, O_NONBLOCK); + return sockflag & O_NONBLOCK; +#endif +} + +void __handlerUpdateCallback(u64 userdata, int cycleslate) { + int buff[2]; + split64(userdata,buff); + __UpdateAdhocctlHandlers(buff[0], buff[1]); +} + +u32 sceNetAdhocInit() { + // Library uninitialized + INFO_LOG(SCENET, "sceNetAdhocInit()"); + if (!netAdhocInited) { + // Clear Translator Memory + memset(&pdp, 0, sizeof(pdp)); + memset(&ptp, 0, sizeof(ptp)); + + // Library initialized + netAdhocInited = true; + + // Return Success + return 0; + } + // Already initialized + return ERROR_NET_ADHOC_ALREADY_INITIALIZED; } u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); - if (netAdhocctlInited) + INFO_LOG(SCENET, "sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); + if (netAdhocctlInited) { return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED; - netAdhocctlInited = true; - + } else if (!g_Config.bEnableWlan) { + // Pretend success but don't actually start the friendfinder thread and stuff. + // Dunno if this is the way to go... + netAdhocctlInited = true; + return 0; + } else if (initNetwork((SceNetAdhocctlAdhocId *)Memory::GetPointer(productAddr)) == 0) { + netAdhocctlInited = true; + eventHandlerUpdate = CoreTiming::RegisterEvent("HandlerUpdateEvent", __handlerUpdateCallback); + friendFinderRunning = true; + friendFinderThread = std::thread(friendFinder); + } else { + WARN_LOG(SCENET, "sceNetAdhocctlInit: Faking success"); + return 0; // Generic error, but just return success to make games conform. + } return 0; } - - -// Seems to always return 0, and write 0 to the pointer.. -// TODO: Eventually research what possible states there are int sceNetAdhocctlGetState(u32 ptrToStatus) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x)", ptrToStatus); - if (Memory::IsValidAddress(ptrToStatus)) - Memory::Write_U32(0, ptrToStatus); - else - ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x): Tried to write invalid location", ptrToStatus); - - return 0; + // Library initialized + if (netAdhocctlInited) { + // Valid Arguments + if (Memory::IsValidAddress(ptrToStatus)) { + // Return Thread Status + Memory::Write_U32(threadStatus, ptrToStatus); + // Return Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } -// Always return -1 since we don't have any real networking... +/** + * Adhoc Emulator PDP Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param bufsize Socket Buffer Size + * @param flag Bitflags (Unused) + * @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_INVALID_ADDR, ADHOC_PORT_NOT_AVAIL, ADHOC_INVALID_PORT, ADHOC_PORT_IN_USE, NET_NO_SPACE + */ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpCreate(%s, %x, %x, %x)", mac, port, bufferSize, unknown); - return -1; + INFO_LOG(SCENET, "sceNetAdhocPdpCreate(%s, %d, %d, %d)", mac, port, bufferSize, unknown); + if (!g_Config.bEnableWlan) { + return -1; + } + + // Library is initialized + SceNetEtherAddr * saddr = (SceNetEtherAddr *)mac; + if (netAdhocInited) { + // Valid Arguments are supplied + if (mac != NULL && bufferSize > 0) { + // Valid MAC supplied + if (isLocalMAC(saddr)) { + //// Unused Port supplied + //if (!_IsPDPPortInUse(port)) {} + // + //// Port is in use by another PDP Socket + //return ERROR_NET_ADHOC_PORT_IN_USE; + + // Create Internet UDP Socket + int usocket = (int)INVALID_SOCKET; + usocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + // Valid Socket produced + if (usocket != INVALID_SOCKET) { + // Enable Port Re-use + //setsockopt(usocket, SOL_SOCKET, SO_REUSEADDR, &_one, sizeof(_one)); NO idea if we need this + // Binding Information for local Port + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + + addr.sin_port = htons(port); // This not safe in any way... + + // Bound Socket to local Port + if (bind(usocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Allocate Memory for Internal Data + SceNetAdhocPdpStat * internal = (SceNetAdhocPdpStat *)malloc(sizeof(SceNetAdhocPdpStat)); + + // Allocated Memory + if (internal != NULL) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPdpStat)); + + // Find Free Translator Index + int i = 0; for (; i < 255; i++) if (pdp[i] == NULL) break; + + // Found Free Translator Index + if (i < 255) { + // Fill in Data + internal->id = usocket; + internal->laddr = *saddr; + internal->lport = port; + internal->rcv_sb_cc = bufferSize; + + // Link Socket to Translator ID + pdp[i] = internal; + + // Forward Port on Router + //sceNetPortOpen("UDP", sport); // I need to figure out how to use this in windows/linux + + // Success + return i + 1; + } + + // Free Memory for Internal Data + free(internal); + } + } + + // Close Socket + closesocket(usocket); + } + + // Default to No-Space Error + return ERROR_NET_NO_SPACE; + } + + // Invalid MAC supplied + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Invalid Arguments were supplied + return ERROR_NET_ADHOC_INVALID_ARG; + } + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -// TODO: Should we really write the struct if we're disconnected? +/** + * Get Adhoc Parameter + * @param parameter OUT: Adhoc Parameter + * @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG + */ int sceNetAdhocctlGetParameter(u32 paramAddr) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr); - struct SceNetAdhocctlParams params; - params.channel = 0; - for (int i = 0; i < 6; i++) - params.bssid[i] = i + 1; - strcpy(params.name, ""); - strcpy(params.nickname, ""); + INFO_LOG(SCENET, "sceNetAdhocctlGetParameter(%u)",paramAddr); + if (!g_Config.bEnableWlan) { + return ERROR_NET_ADHOCCTL_DISCONNECTED; + } - if (Memory::IsValidAddress(paramAddr)) - Memory::WriteStruct(paramAddr, ¶ms); + // Library initialized + if (netAdhocctlInited) { + // Valid Arguments + if (Memory::IsValidAddress(paramAddr)) { + // Copy Parameter + Memory::WriteStruct(paramAddr,¶meter); + // Return Success + return 0; + } - return ERROR_NET_ADHOCCTL_DISCONNECTED; + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } -int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, void *dataLength, u32 timeout, int nonBlock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpSend(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, dataLength, timeout, nonBlock); - return -1; +/** + * Adhoc Emulator PDP Send Call + * @param id Socket File Descriptor + * @param daddr Target MAC Address + * @param dport Target Port + * @param data Data Payload + * @param len Payload Length + * @param timeout Send Timeout + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT, ADHOC_INVALID_DATALEN, ADHOC_SOCKET_ALERTED, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_WOULD_BLOCK, NET_NO_SPACE, NET_INTERNAL + */ +int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, int timeout, int flag) { + INFO_LOG(SCENET, "sceNetAdhocPdpSend(%i, %s, %i, %p, %i, %i, %i)", id, mac, port, data, len, timeout, flag); + if (!g_Config.bEnableWlan) { + return -1; + } + SceNetEtherAddr * daddr = (SceNetEtherAddr *)mac; + uint16 dport = (uint16)port; + + // Really should flatten this with early outs, all this indentation is making me dizzy. + + // Library is initialized + if (netAdhocInited) { + // Valid Port + if (dport != 0) { + // Valid Data Length + if (len > 0) { + // Valid Socket ID + if (id > 0 && id <= 255 && pdp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPdpStat * socket = pdp[id - 1]; + + // Valid Data Buffer + if (data != NULL) { + // Valid Destination Address + if (daddr != NULL) { + // Log Destination + // Schedule Timeout Removal + if (flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); + + // Single Target + if (!isBroadcastMAC(daddr)) { + // Fill in Target Structure + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_port = htons(dport); + + // Get Peer IP + if (resolveMAC((SceNetEtherAddr *)daddr, (uint32_t *)&target.sin_addr.s_addr) == 0) { + // Acquire Network Lock + //_acquireNetworkLock(); + + // Send Data + changeBlockingMode(socket->id, flag); + int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); + changeBlockingMode(socket->id, 0); + + // Free Network Lock + //_freeNetworkLock(); + + // Sent Data + if (sent == len) { + // Success + return 0; + } + + // Blocking Situation + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + } + + // Broadcast Target + else { + // Acquire Network Lock + //_acquireNetworkLock(); + +#ifdef BROADCAST_TO_LOCALHOST + //// Get Local IP Address + //union SceNetApctlInfo info; if (sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) { + // // Fill in Target Structure + // SceNetInetSockaddrIn target; + // target.sin_family = AF_INET; + // sceNetInetInetAton(info.ip, &target.sin_addr); + // target.sin_port = sceNetHtons(dport); + // + // // Send Data + // sceNetInetSendto(socket->id, data, len, ((flag != 0) ? (INET_MSG_DONTWAIT) : (0)), (SceNetInetSockaddr *)&target, sizeof(target)); + //} +#endif + + // Acquire Peer Lock + peerlock.lock(); + + // Iterate Peers + SceNetAdhocctlPeerInfo * peer = friends; + for (; peer != NULL; peer = peer->next) { + // Fill in Target Structure + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_addr.s_addr = peer->ip_addr; + target.sin_port = htons(dport); + + uint8_t * thing = (uint8_t *)&peer->ip_addr; + // printf("Attempting PDP Send to %u.%u.%u.%u on Port %u\n", thing[0], thing[1], thing[2], thing[3], dport); + // Send Data + changeBlockingMode(socket->id, flag); + sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); + changeBlockingMode(socket->id, 0); + } + + // Free Peer Lock + peerlock.unlock(); + + // Free Network Lock + //_freeNetworkLock(); + + // Broadcast never fails! + return 0; + } + } + + // Invalid Destination Address + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Invalid Data Length + return ERROR_NET_ADHOC_INVALID_DATALEN; + } + + // Invalid Destination Port + return ERROR_NET_ADHOC_INVALID_PORT; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; + } -// Return -1 packets since we don't have networking yet.. -int sceNetAdhocPdpRecv(int id, const char *mac, u32 port, void *data, void *dataLength, u32 timeout, int nonBlock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpRecv(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, dataLength, timeout, nonBlock); - return -1; +/** + * Adhoc Emulator PDP Receive Call + * @param id Socket File Descriptor + * @param saddr OUT: Source MAC Address + * @param sport OUT: Source Port + * @param buf OUT: Received Data + * @param len IN: Buffer Size OUT: Received Data Length + * @param timeout Receive Timeout + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_ENOUGH_SPACE, ADHOC_THREAD_ABORTED, NET_INTERNAL + */ +int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLength, u32 timeout, int flag) { + INFO_LOG(SCENET, "sceNetAdhocPdpRecv(%i, %p, %p, %p, %p, %i, %i)", id, addr, port, buf, dataLength, timeout, flag); + if (!g_Config.bEnableWlan) { + return -1; + } + + SceNetEtherAddr *saddr = (SceNetEtherAddr *)addr; + uint16_t * sport = (uint16_t *)port; + int * len = (int *)dataLength; + if (netAdhocInited) { + // Valid Socket ID + if (id > 0 && id <= 255 && pdp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPdpStat * socket = pdp[id - 1]; + + // Valid Arguments + if (saddr != NULL && port != NULL && buf != NULL && len != NULL && *len > 0) { +#ifndef PDP_DIRTY_MAGIC + // Schedule Timeout Removal + if (flag == 1) timeout = 0; +#else + // Nonblocking Simulator + int wouldblock = 0; + + // Minimum Timeout + uint32_t mintimeout = 250000; + + // Nonblocking Call + if (flag == 1) { + // Erase Nonblocking Flag + flag = 0; + + // Set Wouldblock Behaviour + wouldblock = 1; + + // Set Minimum Timeout (250ms) + if (timeout < mintimeout) timeout = mintimeout; + } +#endif + + // Apply Receive Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); + + // Sender Address + sockaddr_in sin; + + // Set Address Length (so we get the sender ip) + socklen_t sinlen = sizeof(sin); + //sin.sin_len = (uint8_t)sinlen; + // Acquire Network Lock + //_acquireNetworkLock(); + + // Receive Data + changeBlockingMode(socket->id,flag); + int received = recvfrom(socket->id, (char *)buf, *len,0,(sockaddr *)&sin, &sinlen); + changeBlockingMode(socket->id,0); + + // Received Data + if (received > 0) { + // Peer MAC + SceNetEtherAddr mac; + + // Find Peer MAC + if (resolveIP(sin.sin_addr.s_addr, &mac) == 0) { + // Provide Sender Information + *saddr = mac; + *sport = htons(sin.sin_port); + + // Save Length + *len = received; + + // Free Network Lock + //_freeNetworkLock(); + + // Return Success + return 0; + } + } + + // Free Network Lock + //_freeNetworkLock(); + +#ifdef PDP_DIRTY_MAGIC + // Restore Nonblocking Flag for Return Value + if (wouldblock) flag = 1; +#endif + + // Nothing received + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } // Assuming < 0 for failure, homebrew SDK doesn't have much to say about this one.. int sceNetAdhocSetSocketAlert(int id, int flag) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocSetSocketAlert(%d, %d)", id, flag); + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocSetSocketAlert(%d, %d)", id, flag); return -1; } @@ -201,10 +623,52 @@ int sceNetAdhocPollSocket(u32 socketStructAddr, int count, int timeout, int nonb return -1; } - +/** + * Adhoc Emulator PDP Socket Delete + * @param id Socket File Descriptor + * @param flag Bitflags (Unused) + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID + */ int sceNetAdhocPdpDelete(int id, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpDelete(%d, %d)", id, unknown); - return 0; + INFO_LOG(SCENET, "sceNetAdhocPdpDelete(%d, %d)", id, unknown); + if (!g_Config.bEnableWlan) { + return 0; + } + // Library is initialized + if (netAdhocInited) { + // Valid Arguments + if (id > 0 && id <= 255) { + // Cast Socket + SceNetAdhocPdpStat * sock = pdp[id - 1]; + + // Valid Socket + if (socket != NULL) { + // Close Connection + closesocket(sock->id); + + // Remove Port Forward from Router + //sceNetPortClose("UDP", socket->lport); + + // Free Memory + // free(socket); + + // Free Translation Slot + pdp[id - 1] = NULL; + + // Success + return 0; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } int sceNetAdhocctlGetAdhocId(u32 productStructAddr) { @@ -213,15 +677,113 @@ int sceNetAdhocctlGetAdhocId(u32 productStructAddr) { } int sceNetAdhocctlScan() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlScan()"); - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); + INFO_LOG(SCENET, "sceNetAdhocctlScan()"); - return 0; + // Library initialized + if (netAdhocctlInited) { + // Not connected + if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) { + threadStatus = ADHOCCTL_STATE_SCANNING; + + // Prepare Scan Request Packet + uint8_t opcode = OPCODE_SCAN; + + // Send Scan Request Packet + send(metasocket, (char *)&opcode, 1, 0); + + // Return Success + return 0; + } + + // Library is busy + return ERROR_NET_ADHOCCTL_BUSY; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } -int sceNetAdhocctlGetScanInfo() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetScanInfo()"); - return 0; +int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) { + INFO_LOG(SCENET, "sceNetAdhocctlGetScanInfo(%08x, %08x)", size, bufAddr); + if (!g_Config.bEnableWlan) { + return 0; + } + int * buflen = (int *)Memory::GetPointer(size); + SceNetAdhocctlScanInfo * buf = NULL; + if (Memory::IsValidAddress(bufAddr)) { + buf = (SceNetAdhocctlScanInfo *)Memory::GetPointer(bufAddr); + } + // Library initialized + if (netAdhocctlInited) { + // Minimum Argument Requirements + if (buflen != NULL) { + // Multithreading Lock + peerlock.lock(); + + // Length Returner Mode + if (buf == NULL) *buflen = countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); + + // Normal Information Mode + else { + // Clear Memory + memset(buf, 0, *buflen); + + // Network Discovery Counter + int discovered = 0; + + // Count requested Networks + int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfo); + + // Minimum Argument Requirements + if (requestcount > 0) { + // Group List Element + SceNetAdhocctlScanInfo * group = networks; + + // Iterate Group List + for (; group != NULL && discovered < requestcount; group = group->next) { + // Copy Group Information + buf[discovered] = *group; + + // Exchange Adhoc Channel + // sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel); + + // Fake Channel Number 1 on Automatic Channel + // if (buf[discovered].channel == 0) buf[discovered].channel = 1; + + //Always Fake Channel 1 + buf[discovered].channel = 1; + + // Increase Discovery Counter + discovered++; + } + + // Link List + int i = 0; for (; i < discovered - 1; i++) { + // Link Network + buf[i].next = &buf[i + 1]; + } + + // Fix Last Element + if (discovered > 0) buf[discovered - 1].next = NULL; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlScanInfo); + } + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + + // Generic Error + return -1; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } // TODO: How many handlers can the PSP actually have for Adhocctl? @@ -261,22 +823,58 @@ u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) { return retval; } -int sceNetAdhocctlConnect(u32 ptrToGroupName) { - if (Memory::IsValidAddress(ptrToGroupName)) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); - } else { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(%x)", ptrToGroupName); - } - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); - - return 0; -} - u32 sceNetAdhocctlDisconnect() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlDisconnect()"); - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); + INFO_LOG(SCENET, "sceNetAdhocctlDisconnect()"); + if (!g_Config.bEnableWlan) { + return 0; + } + // Library initialized + if (netAdhocctlInited) { + // Connected State (Adhoc Mode) + if (threadStatus == ADHOCCTL_STATE_CONNECTED) { + // Clear Network Name + memset(¶meter.group_name, 0, sizeof(parameter.group_name)); - return 0; + // Set Disconnected State + threadStatus = ADHOCCTL_STATE_DISCONNECTED; + + // Set HUD Connection Status + //setConnectionStatus(0); + + // Prepare Packet + uint8_t opcode = OPCODE_DISCONNECT; + + // Acquire Network Lock + //_acquireNetworkLock(); + + // Send Disconnect Request Packet + send(metasocket, (const char *)&opcode, 1, 0); + + // Free Network Lock + //_freeNetworkLock(); + + // Multithreading Lock + peerlock.lock(); + + // Clear Peer List + freeFriendsRecursive(friends); + + // Delete Peer Reference + friends = NULL; + + // Multithreading Unlock + peerlock.unlock(); + } + + // Notify Event Handlers (even if we weren't connected, not doing this will freeze games like God Eater, which expect this behaviour) + __UpdateAdhocctlHandlers(ADHOCCTL_EVENT_DISCONNECT,0); + + // Return Success + return 0; + } + + // Library uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } u32 sceNetAdhocctlDelHandler(u32 handlerID) { @@ -291,8 +889,24 @@ u32 sceNetAdhocctlDelHandler(u32 handlerID) { } int sceNetAdhocctlTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlTerm()"); - netAdhocctlInited = false; + INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); + if (!g_Config.bEnableWlan) { + return 0; + } + + if (netAdhocctlInited) { + netAdhocctlInited = false; + friendFinderRunning = false; + if (friendFinderThread.joinable()) { + friendFinderThread.join(); + } + // Free stuff here + closesocket(metasocket); + metasocket = (int)INVALID_SOCKET; +#ifdef _MSC_VER + WSACleanup(); +#endif + } return 0; } @@ -312,9 +926,74 @@ int sceNetAdhocctlGetPeerInfo(const char *mac, int size, u32 peerInfoAddr) { return -1; } +/** + * Create and / or Join a Virtual Network of the specified Name + * @param group_name Virtual Network Name + * @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG, ADHOCCTL_BUSY + */ int sceNetAdhocctlCreate(const char *groupName) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreate(%s)", groupName); - return -1; + INFO_LOG(SCENET, "sceNetAdhocctlCreate(%s)", groupName); + if (!g_Config.bEnableWlan) { + return -1; + } + + const SceNetAdhocctlGroupName * groupNameStruct = (const SceNetAdhocctlGroupName *)groupName; + // Library initialized + if (netAdhocctlInited) { + // Valid Argument + if (validNetworkName(groupNameStruct)) { + // Disconnected State + if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) { + // Set Network Name + if (groupNameStruct != NULL) parameter.group_name = *groupNameStruct; + + // Reset Network Name + else memset(¶meter.group_name, 0, sizeof(parameter.group_name)); + + // Prepare Connect Packet + SceNetAdhocctlConnectPacketC2S packet; + + // Clear Packet Memory + memset(&packet, 0, sizeof(packet)); + + // Set Packet Opcode + packet.base.opcode = OPCODE_CONNECT; + + // Set Target Group + if (groupNameStruct != NULL) packet.group = *groupNameStruct; + + // Acquire Network Lock + + // Send Packet + send(metasocket, (const char *)&packet, sizeof(packet), 0); + + // Free Network Lock + + // Set HUD Connection Status + //setConnectionStatus(1); + + // Return Success + return 0; + } + + // Connected State + return ERROR_NET_ADHOCCTL_BUSY; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; +} + +int sceNetAdhocctlConnect(u32 ptrToGroupName) { + if (Memory::IsValidAddress(ptrToGroupName)) { + INFO_LOG(SCENET, "sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); + return sceNetAdhocctlCreate(Memory::GetCharPointer(ptrToGroupName)); + } else { + return ERROR_NET_ADHOC_INVALID_ADDR; + } } int sceNetAdhocctlCreateEnterGameMode(const char *groupName, int unknown, int playerNum, u32 macsAddr, int timeout, int unknown2) { @@ -328,13 +1007,34 @@ int sceNetAdhocctlJoinEnterGameMode(const char *groupName, const char *macAddr, } int sceNetAdhocTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocTerm()"); - // Seems to return this when called a second time after being terminated without another initialisation - if(!netAdhocInited) - return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND; - netAdhocInited = false; + INFO_LOG(SCENET, "sceNetAdhocTerm()"); + if (!g_Config.bEnableWlan) { + return 0; + } - return 0; + // Library is initialized + if (netAdhocInited) { + // Delete PDP Sockets + deleteAllPDP(); + + // Delete PTP Sockets + deleteAllPTP(); + + // Delete Gamemode Buffer + //_deleteAllGMB(); + + // Terminate Internet Library + //sceNetInetTerm(); + + // Unload Internet Modules (Just keep it in memory... unloading crashes?!) + // if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET); + // Library shutdown + netAdhocInited = false; + return 0; + } else { + // Seems to return this when called a second time after being terminated without another initialisation + return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND; + } } int sceNetAdhocGetPdpStat(int structSize, u32 structAddr) { @@ -342,49 +1042,834 @@ int sceNetAdhocGetPdpStat(int structSize, u32 structAddr) { return 0; } -int sceNetAdhocGetPtpStat(int structSize, u32 structAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPtpStat(%i, %08x)", structSize, structAddr); + +/** + * Adhoc Emulator PTP Socket List Getter + * @param buflen IN: Length of Buffer in Bytes OUT: Required Length of Buffer in Bytes + * @param buf PTP Socket List Buffer (can be NULL if you wish to receive Required Length) + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED + */ +int sceNetAdhocGetPtpStat(u32 structSize, u32 structAddr) { + // Spams a lot + VERBOSE_LOG(SCENET,"sceNetAdhocGetPtpStat(%u,%u)",structSize,structAddr); + + if (!g_Config.bEnableWlan) { + return 0; + } + + int * buflen = (int *)Memory::GetPointer(structSize); + // Library is initialized + if (netAdhocInited) { + // Length Returner Mode + if (buflen != NULL && !Memory::IsValidAddress(structAddr)) { + // Return Required Size + *buflen = sizeof(SceNetAdhocPtpStat) * getPTPSocketCount(); + + // Success + return 0; + } + + // Status Returner Mode + else if (buflen != NULL && Memory::IsValidAddress(structAddr)) { + // Socket Count + int socketcount = getPTPSocketCount(); + SceNetAdhocPtpStat * buf = (SceNetAdhocPtpStat *)Memory::GetPointer(structAddr); + + // Figure out how many Sockets we will return + int count = *buflen / sizeof(SceNetAdhocPtpStat); + if (count > socketcount) count = socketcount; + + // Copy Counter + int i = 0; + + // Iterate Sockets + int j = 0; for (; j < 255 && i < count; j++) { + // Active Socket + if (ptp[j] != NULL) { + // Copy Socket Data from internal Memory + buf[i] = *ptp[j]; + + // Fix Client View Socket ID + buf[i].id = j + 1; + + // Write End of List Reference + buf[i].next = 0; + + // Link previous Element to this one + if (i > 0) + buf[i-1].next = structAddr + (i*sizeof(SceNetAdhocPtpStat)) + sizeof(SceNetAdhocPtpStat); + + // Increment Counter + i++; + } + } + + // Update Buffer Length + *buflen = i * sizeof(SceNetAdhocPtpStat); + + // Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; +} + + +/** + * Adhoc Emulator PTP Active Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param daddr Target MAC + * @param dport Target Port + * @param bufsize Socket Buffer Size + * @param rexmt_int Retransmit Interval (in Microseconds) + * @param rexmt_cnt Retransmit Count + * @param flag Bitflags (Unused) + * @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT + */ +int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, int dport, int bufsize, int rexmt_int, int rexmt_cnt, int unknown) { + INFO_LOG(SCENET, "sceNetAdhocPtpOpen(%s,%d,%s,%d,%d,%d,%d,%d)", srcmac, sport, dstmac,dport,bufsize, rexmt_int, rexmt_cnt, unknown); + if (!g_Config.bEnableWlan) { + return 0; + } + SceNetEtherAddr * saddr = (SceNetEtherAddr *)srcmac; + SceNetEtherAddr * daddr = (SceNetEtherAddr *)dstmac; + // Library is initialized + if (netAdhocInited) { + // Valid Addresses + if (saddr != NULL && isLocalMAC(saddr) && daddr != NULL && !isBroadcastMAC(daddr)) { + // Random Port required + if (sport == 0) { + // Find unused Port + // while (sport == 0 || _IsPTPPortInUse(sport)) { + // // Generate Port Number + // sport = (uint16_t)_getRandomNumber(65535); + // } + } + + // Valid Ports + if (!isPTPPortInUse(sport) && dport != 0) { + // Valid Arguments + if (bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0) { + // Create Infrastructure Socket + int tcpsocket = (int)INVALID_SOCKET; + tcpsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + // Valid Socket produced + if (tcpsocket > 0) { + // Enable Port Re-use + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); + + // Binding Information for local Port + sockaddr_in addr; + // addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(sport); + + // Bound Socket to local Port + if (bind(tcpsocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if (internal != NULL) { + // Find Free Translator ID + int i = 0; for (; i < 255; i++) if (ptp[i] == NULL) break; + + // Found Free Translator ID + if (i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Infrastructure Socket ID + internal->id = tcpsocket; + + // Copy Address Information + internal->laddr = *saddr; + internal->paddr = *daddr; + internal->lport = sport; + internal->pport = dport; + + // Set Buffer Size + internal->rcv_sb_cc = bufsize; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", sport); + + // Return PTP Socket Pointer + return i + 1; + } + + // Free Memory + free(internal); + } + } + + // Close Socket + closesocket(tcpsocket); + } + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Ports + return ERROR_NET_ADHOC_INVALID_PORT; + } + + // Invalid Addresses + return ERROR_NET_ADHOC_INVALID_ADDR; + } + return 0; } -int sceNetAdhocPtpOpen(const char *srcmac, int srcport, const char *dstmac, int dstport, int bufsize, int retryDelay, int retryCount, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpOpen(%s : %i, %s : %i, %i, %i, %i, %08x)", srcmac, srcport, dstmac, dstport, bufsize, retryDelay, retryCount, unknown); - return 0; + +/** + * Adhoc Emulator PTP Connection Acceptor + * @param id Socket File Descriptor + * @param addr OUT: Peer MAC Address + * @param port OUT: Peer Port + * @param timeout Accept Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return Socket ID >= 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_LISTENED, ADHOC_THREAD_ABORTED, NET_INTERNAL + */ +int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeout, int flag) { + + SceNetEtherAddr * addr = NULL; + if (Memory::IsValidAddress(peerMacAddrPtr)) { + addr = Memory::GetStruct(peerMacAddrPtr); + } + uint16_t * port = NULL; + if (Memory::IsValidAddress(peerPortPtr)) { + port = (uint16_t *)Memory::GetPointer(peerPortPtr); + } + INFO_LOG(SCENET, "sceNetAdhocPtpAccept(%d,%s,%d,%u,%d)",id, addr->data,*port,timeout, flag); + if (!g_Config.bEnableWlan) { + return 0; + } + + // Library is initialized + if (netAdhocInited) { + // Valid Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Listener Socket + if (socket->state == PTP_STATE_LISTEN) { + // Valid Arguments + if (addr != NULL && port != NULL) { + // Address Information + sockaddr_in peeraddr; + memset(&peeraddr, 0, sizeof(peeraddr)); + socklen_t peeraddrlen = sizeof(peeraddr); + // Local Address Information + sockaddr_in local; + memset(&local, 0, sizeof(local)); + socklen_t locallen = sizeof(local); + + // Grab Nonblocking Flag + uint32_t nbio = getBlockingFlag(socket->id); + // Switch to Nonblocking Behaviour + if (nbio == 0) { + // Overwrite Socket Option + changeBlockingMode(socket->id,1); + } + + // Accept Connection + int newsocket = accept(socket->id, (sockaddr *)&peeraddr, &peeraddrlen); + + // Blocking Behaviour + if (!flag && newsocket == -1) { + // Get Start Time + uint32_t starttime = (uint32_t)(real_time_now()*1000.0); + + // Retry until Timeout hits + while ((timeout == 0 ||((uint32_t)(real_time_now()*1000.0) - starttime) < (uint32_t)timeout) && newsocket == -1) { + // Accept Connection + newsocket = accept(socket->id, (sockaddr *)&peeraddr, &peeraddrlen); + + // Wait a bit... + sleep_ms(1); + } + } + + // Restore Blocking Behaviour + if (nbio == 0) { + // Restore Socket Option + changeBlockingMode(socket->id,0); + } + + // Accepted New Connection + if (newsocket > 0) { + // Enable Port Re-use + setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); + + // Grab Local Address + if (getsockname(newsocket, (sockaddr *)&local, &locallen) == 0) { + // Peer MAC + SceNetEtherAddr mac; + + // Find Peer MAC + if (resolveIP(peeraddr.sin_addr.s_addr, &mac) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if (internal != NULL) { + // Find Free Translator ID + int i = 0; for (; i < 255; i++) if (ptp[i] == NULL) break; + + // Found Free Translator ID + if (i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Socket Descriptor to Structure + internal->id = newsocket; + + // Copy Local Address Data to Structure + getLocalMac(&internal->laddr); + internal->lport = htons(local.sin_port); + + // Copy Peer Address Data to Structure + internal->paddr = mac; + internal->pport = htons(peeraddr.sin_port); + + // Set Connected State + internal->state = PTP_STATE_ESTABLISHED; + + // Return Peer Address Information + *addr = internal->paddr; + *port = internal->pport; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", internal->lport); + + // Return Socket + return i + 1; + } + + // Free Memory + free(internal); + } + } + } + + // Close Socket + closesocket(newsocket); + } + + // Action would block + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Client Socket + return ERROR_NET_ADHOC_NOT_LISTENED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpAccept(%i, %08x, %08x, %i, %i)", id, peerMacAddrPtr, peerPortPtr, timeout, nonblock); - return 0; + +/** + * Adhoc Emulator PTP Connection Opener + * @param id Socket File Descriptor + * @param timeout Connect Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_CONNECTION_REFUSED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_OPENED, ADHOC_THREAD_ABORTED, NET_INTERNAL + */ +int sceNetAdhocPtpConnect(int id, int timeout, int flag) { + INFO_LOG(SCENET, "sceNetAdhocPtpConnect(%i, %i, %08x)", id, timeout, flag); + if (!g_Config.bEnableWlan) { + return 0; + } + + // Library is initialized + if (netAdhocInited) + { + // Valid Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Valid Client Socket + if (socket->state == 0) { + // Target Address + sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + + // Setup Target Address + // sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(socket->pport); + + // Grab Peer IP + if (resolveMAC(&socket->paddr, (uint32_t *)&sin.sin_addr.s_addr) == 0) { + // Grab Nonblocking Flag + uint32_t nbio = getBlockingFlag(socket->id); + // Switch to Nonblocking Behaviour + if (nbio == 0) { + // Overwrite Socket Option + changeBlockingMode(socket->id, 1); + } + + // Connect Socket to Peer (Nonblocking) + int connectresult = connect(socket->id, (sockaddr *)&sin, sizeof(sin)); + + // Grab Error Code + int errorcode = errno; + + // Restore Blocking Behaviour + if (nbio == 0) { + // Restore Socket Option + changeBlockingMode(socket->id,0); + } + + // Instant Connection (Lucky!) + if (connectresult == 0 || (connectresult == -1 && errorcode == EISCONN)) { + // Set Connected State + socket->state = PTP_STATE_ESTABLISHED; + + // Success + return 0; + } + + // Connection in Progress + else if (connectresult == -1 && errorcode == EINPROGRESS) { + // Nonblocking Mode + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Blocking Mode + else { + // Grab Connection Start Time + uint32_t starttime = (uint32_t)(real_time_now()*1000.0); + + // Peer Information (for Connection-Polling) + sockaddr_in peer; + memset(&peer, 0, sizeof(peer)); + socklen_t peerlen = sizeof(peer); + // Wait for Connection + while ((timeout == 0 || ( (uint32_t)(real_time_now()*1000.0) - starttime) < (uint32_t)timeout) && getpeername(socket->id, (sockaddr *)&peer, &peerlen) != 0) { + // Wait 1ms + sleep_ms(1); + } + + // Connected in Time + if (sin.sin_addr.s_addr == peer.sin_addr.s_addr/* && sin.sin_port == peer.sin_port*/) { + // Set Connected State + socket->state = PTP_STATE_ESTABLISHED; + + // Success + return 0; + } + + // Timeout occured + return ERROR_NET_ADHOC_TIMEOUT; + } + } + } + + // Peer not found + return ERROR_NET_ADHOC_CONNECTION_REFUSED; + } + + // Not a valid Client Socket + return ERROR_NET_ADHOC_NOT_OPENED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpConnect(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpConnect(%i, %i, %i)", id, timeout, nonblock); - return -1; -} +/** + * Adhoc Emulator PTP Socket Closer + * @param id Socket File Descriptor + * @param flag Bitflags (Unused) + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED + */ int sceNetAdhocPtpClose(int id, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpClose(%i, %i)", id, unknown); - return 0; + INFO_LOG(SCENET,"sceNetAdhocPtpClose(%d,%d)",id,unknown); + if (!g_Config.bEnableWlan) { + return 0; + } + // Library is initialized + if (netAdhocInited) { + // Valid Arguments & Atleast one Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Close Connection + closesocket(socket->id); + + // Remove Port Forward from Router + // sceNetPortClose("TCP", socket->lport); + + // Free Memory + free(socket); + + // Free Reference + ptp[id - 1] = NULL; + + // Success + return 0; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpListen(const char *srcmac, int srcport, int bufsize, int retryDelay, int retryCount, int queue, int unk) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpListen(%s : %i, %i, %i, %i, %i, %i)", srcmac, srcport, bufsize, retryDelay, retryCount, queue, unk); - return 0; + +/** + * Adhoc Emulator PTP Passive Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param bufsize Socket Buffer Size + * @param rexmt_int Retransmit Interval (in Microseconds) + * @param rexmt_cnt Retransmit Count + * @param backlog Size of Connection Queue + * @param flag Bitflags (Unused) + * @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_PORT_NOT_AVAIL, ADHOC_PORT_IN_USE, NET_NO_SPACE + */ +int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int rexmt_int, int rexmt_cnt, int backlog, int unk) { + INFO_LOG(SCENET, "sceNetAdhocPtpListen(%s,%d,%d,%d,%d,%d,%d)",srcmac,sport,bufsize,rexmt_int,rexmt_cnt,backlog,unk); + if (!g_Config.bEnableWlan) { + return 0; + } + // Library is initialized + SceNetEtherAddr * saddr = (SceNetEtherAddr *)srcmac; + if (netAdhocInited) { + // Valid Address + if (saddr != NULL && isLocalMAC(saddr)) + { + // Random Port required + if (sport == 0) { + // Find unused Port + // while (sport == 0 || __IsPTPPortInUse(sport)) + // { + // // Generate Port Number + // sport = (uint16_t)_getRandomNumber(65535); + // } + } + + // Valid Ports + if (!isPTPPortInUse(sport)) { + // Valid Arguments + if (bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0 && backlog > 0) + { + // Create Infrastructure Socket + int tcpsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + // Valid Socket produced + if (tcpsocket > 0) { + // Enable Port Re-use + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); + + // Binding Information for local Port + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(sport); + + // Bound Socket to local Port + if (bind(tcpsocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Switch into Listening Mode + if (listen(tcpsocket, backlog) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if (internal != NULL) { + // Find Free Translator ID + int i = 0; for (; i < 255; i++) if (ptp[i] == NULL) break; + + // Found Free Translator ID + if (i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Infrastructure Socket ID + internal->id = tcpsocket; + + // Copy Address Information + internal->laddr = *saddr; + internal->lport = sport; + + // Flag Socket as Listener + internal->state = PTP_STATE_LISTEN; + + // Set Buffer Size + internal->rcv_sb_cc = bufsize; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", sport); + + // Return PTP Socket Pointer + return i + 1; + } + + // Free Memory + free(internal); + } + } + } + + // Close Socket + closesocket(tcpsocket); + } + + // Socket not available + return ERROR_NET_ADHOC_SOCKET_ID_NOT_AVAIL; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Ports + return ERROR_NET_ADHOC_PORT_IN_USE; + } + + // Invalid Addresses + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpSend(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpSend(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; +/** + * Adhoc Emulator PTP Sender + * @param id Socket File Descriptor + * @param data Data Payload + * @param len IN: Length of Payload OUT: Sent Data (in Bytes) + * @param timeout Send Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_CONNECTED, ADHOC_THREAD_ABORTED, ADHOC_INVALID_DATALEN, ADHOC_DISCONNECTED, NET_INTERNAL, NET_NO_SPACE + */ +int sceNetAdhocPtpSend(int id, u32 dataAddr, u32 dataSizeAddr, int timeout, int flag) { + INFO_LOG(SCENET, "sceNetAdhocPtpSend(%d,%08x,%08x,%d,%d)", id, dataAddr, dataSizeAddr, timeout, flag); + if (!g_Config.bEnableWlan) { + return 0; + } + int * len = (int *)Memory::GetPointer(dataSizeAddr); + const char * data = Memory::GetCharPointer(dataAddr); + // Library is initialized + if (netAdhocInited) { + // Valid Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Connected Socket + if (socket->state == PTP_STATE_ESTABLISHED) { + // Valid Arguments + if (data != NULL && len != NULL && *len > 0) { + // Schedule Timeout Removal + if (flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); + + // Acquire Network Lock + // _acquireNetworkLock(); + + // Send Data + changeBlockingMode(socket->id, flag); + int sent = send(socket->id, data, *len, 0); + int error = errno; + changeBlockingMode(socket->id, 0); + + // Free Network Lock + // _freeNetworkLock(); + + // Success + if (sent > 0) { + // Save Length + *len = sent; + + // Return Success + return 0; + } + + // Non-Critical Error + else if (sent == -1 && error == EAGAIN) { + // Blocking Situation + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Change Socket State + socket->state = PTP_STATE_CLOSED; + + // Disconnected + return ERROR_NET_ADHOC_DISCONNECTED; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Not connected + return ERROR_NET_ADHOC_NOT_CONNECTED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpRecv(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; + +/** + * Adhoc Emulator PTP Receiver + * @param id Socket File Descriptor + * @param buf Data Buffer + * @param len IN: Buffersize OUT: Received Data (in Bytes) + * @param timeout Receive Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_DISCONNECTED, NET_INTERNAL + */ +int sceNetAdhocPtpRecv(int id, u32 dataAddr, u32 dataSizeAddr, int timeout, int flag) { + INFO_LOG(SCENET, "sceNetAdhocPtpRecv(%d,%08x,%08x,%d,%d)", id, dataAddr, dataSizeAddr, timeout, flag); + if (!g_Config.bEnableWlan) { + return 0; + } + void * buf = (void *)Memory::GetPointer(dataAddr); + int * len = (int *)Memory::GetPointer(dataSizeAddr); + // Library is initialized + if (netAdhocInited) { + // Valid Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL && ptp[id - 1]->state == PTP_STATE_ESTABLISHED) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Valid Arguments + if (buf != NULL && len != NULL && *len > 0) { + // Schedule Timeout Removal + if (flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); + + // Acquire Network Lock + // _acquireNetworkLock(); + + // Receive Data + changeBlockingMode(socket->id, flag); + int received = recv(socket->id, (char *)buf, *len, 0); + int error = errno; + changeBlockingMode(socket->id, 0); + + // Free Network Lock + // _freeNetworkLock(); + + // Received Data + if (received > 0) { + // Save Length + *len = received; + + // Return Success + return 0; + } + + // Non-Critical Error + else if (received == -1 && error == EAGAIN) { + // Blocking Situation + if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Change Socket State + socket->state = PTP_STATE_CLOSED; + + // Disconnected + return ERROR_NET_ADHOC_DISCONNECTED; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } +/** + * Adhoc Emulator PTP Flusher + * @param id Socket File Descriptor + * @param timeout Flush Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_DISCONNECTED, ADHOC_NOT_CONNECTED, NET_INTERNAL + */ int sceNetAdhocPtpFlush(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpFlush(%i, %i, %i)", id, timeout, nonblock); - return 0; + INFO_LOG(SCENET,"sceNetAdhocPtpFlush(%d,%d,%d)", id, timeout, nonblock); + if (!g_Config.bEnableWlan) { + return 0; + } + + // Library initialized + if (netAdhocInited) { + // Valid Socket + if (id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Dummy Result + return 0; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + // Library uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } int sceNetAdhocGameModeCreateMaster(u32 data, int size) { @@ -423,12 +1908,19 @@ int sceNetAdhocGetSocketAlert() { } int sceNetAdhocMatchingInit(u32 memsize) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingInit(%08x)", memsize); - if (netAdhocMatchingInited) - return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; - netAdhocMatchingInited = true; + // Uninitialized Library + if (!netAdhocMatchingInited) { + // Save Fake Pool Size + fakePoolSize = memsize; - return 0; + // Initialize Library + netAdhocMatchingInited = true; + + // Return Success + return 0; + } else { + return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; + } } int sceNetAdhocMatchingTerm() { @@ -441,9 +1933,106 @@ int sceNetAdhocMatchingTerm() { // Presumably returns a "matchingId". -int sceNetAdhocMatchingCreate(int mode, int maxPeers, int port, int bufSize, int helloDelay, int pingDelay, int initCount, int msgDelay, u32 callbackAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCreate(%i, %i, %i, %i, %i, %i, %i, %i, %08x)", mode, maxPeers, port, bufSize, helloDelay, pingDelay, initCount, msgDelay, callbackAddr); - return -1; +int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int hello_int, int keepalive_int, int init_count, int rexmt_int, u32 callbackAddr) { + INFO_LOG(SCENET, "sceNetAdhocMatchingCreate"); + if (!g_Config.bEnableWlan) { + return -1; + } + + SceNetAdhocMatchingHandler handler; + handler.entryPoint = callbackAddr; + + // Library initialized + if (netAdhocMatchingInited) { + // Valid Member Limit + if (maxnum > 1 && maxnum <= 16) { + // Valid Receive Buffer size + if (rxbuflen >= 1024) { + // Valid Arguments + if (mode >= 1 && mode <= 3) { + // Iterate Matching Contexts + SceNetAdhocMatchingContext * item = contexts; for (; item != NULL; item = item->next) { + // Port Match found + if (item->port == port) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Allocate Context Memory + SceNetAdhocMatchingContext * context = (SceNetAdhocMatchingContext *)malloc(sizeof(SceNetAdhocMatchingContext)); + + // Allocated Memory + if (context != NULL) { + // Create PDP Socket + SceNetEtherAddr localmac; getLocalMac(&localmac); + const char * mac = (const char *)&localmac.data; + int socket = sceNetAdhocPdpCreate(mac, (uint32_t)port, rxbuflen, 0); + // Created PDP Socket + if (socket > 0) { + // Clear Memory + memset(context, 0, sizeof(SceNetAdhocMatchingContext)); + + // Allocate Receive Buffer + context->rxbuf = (uint8_t *)malloc(rxbuflen); + + // Allocated Memory + if (context->rxbuf != NULL) { + // Clear Memory + memset(context->rxbuf, 0, rxbuflen); + + // Fill in Context Data + context->id = findFreeMatchingID(); + context->mode = mode; + context->maxpeers = maxnum; + context->port = port; + context->socket = socket; + context->rxbuflen = rxbuflen; + context->hello_int = hello_int; + context->keepalive_int = 500000; + //context->keepalive_int = keepalive_int; + context->resendcounter = init_count; + context->keepalivecounter = 100; + //context->keepalivecounter = init_count; + context->resend_int = rexmt_int; + context->handler = handler; + + // Fill in Selfpeer + context->mac = localmac; + + // Link Context + context->next = contexts; + contexts = context; + + // Return Matching ID + return context->id; + } + + // Close PDP Socket + sceNetAdhocPdpDelete(socket, 0); + } + + // Free Memory + free(context); + + // Port in use + if (socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Out of Memory + return ERROR_NET_ADHOC_MATCHING_NO_SPACE; + } + + // InvalidERROR_NET_Arguments + return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; + } + + // Invalid Receive Buffer Size + return ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT; + } + + // Invalid Member Limit + return ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM; + } + // Uninitialized Library + return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; } int sceNetAdhocMatchingStart(int matchingId, int evthPri, int evthStack, int inthPri, int inthStack, int optLen, u32 optDataAddr) { @@ -516,8 +2105,8 @@ const HLEFunction sceNetAdhoc[] = { {0xA62C6F57, WrapI_V, "sceNetAdhocTerm"}, {0x0AD043ED, WrapI_U, "sceNetAdhocctlConnect"}, {0x6f92741b, WrapI_CUIU, "sceNetAdhocPdpCreate"}, - {0xabed3790, WrapI_ICUVVUI, "sceNetAdhocPdpSend"}, - {0xdfe53e03, WrapI_ICUVVUI, "sceNetAdhocPdpRecv"}, + {0xabed3790, WrapI_ICUVIII, "sceNetAdhocPdpSend"}, + {0xdfe53e03, WrapI_IVVVVUI, "sceNetAdhocPdpRecv"}, {0x7f27bb5e, WrapI_II, "sceNetAdhocPdpDelete"}, {0xc7c1fc57, WrapI_IU, "sceNetAdhocGetPdpStat"}, {0x157e6225, WrapI_II, "sceNetAdhocPtpClose"}, @@ -528,7 +2117,7 @@ const HLEFunction sceNetAdhoc[] = { {0xe08bdac1, WrapI_CIIIIII, "sceNetAdhocPtpListen"}, {0xfc6fc07b, WrapI_III, "sceNetAdhocPtpConnect"}, {0x9ac2eeac, WrapI_III, "sceNetAdhocPtpFlush"}, - {0xb9685118, WrapI_IU, "sceNetAdhocGetPtpStat"}, + {0xb9685118, WrapI_UU, "sceNetAdhocGetPtpStat"}, {0x3278ab0c, WrapI_CUI, "sceNetAdhocGameModeCreateReplica"}, {0x98c204c8, WrapI_V, "sceNetAdhocGameModeUpdateMaster"}, {0xfa324b4e, WrapI_IU, "sceNetAdhocGameModeUpdateReplica"}, @@ -569,9 +2158,85 @@ int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) { return -1; } + int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr); - return -1; + INFO_LOG(SCENET, "sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr); + if (!g_Config.bEnableWlan) { + return -1; + } + + int * buflen = (int *)Memory::GetPointer(sizeAddr); + SceNetAdhocctlPeerInfoEmu * buf = NULL; + if (Memory::IsValidAddress(bufAddr)) { + buf = (SceNetAdhocctlPeerInfoEmu *)Memory::GetPointer(bufAddr); + } + // Initialized Library + if (netAdhocctlInited) { + // Minimum Arguments + if (buflen != NULL) { + // Multithreading Lock + peerlock.lock(); + + // Length Calculation Mode + if (buf == NULL) *buflen = getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfoEmu); + + // Normal Mode + else { + // Discovery Counter + int discovered = 0; + + // Calculate Request Count + int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfoEmu); + + // Clear Memory + memset(buf, 0, *buflen); + + // Minimum Arguments + if (requestcount > 0) { + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for (; peer != NULL && discovered < requestcount; peer = peer->next) { + // Fake Receive Time + peer->last_recv = (uint64_t)time(NULL); + + // Copy Peer Info + buf[discovered].nickname = peer->nickname; + buf[discovered].mac_addr = peer->mac_addr; + buf[discovered].ip_addr = peer->ip_addr; + buf[discovered].last_recv = peer->last_recv; + discovered++; + + } + + // Link List + int i = 0; for (; i < discovered - 1; i++) { + // Link Network + buf[i].next = bufAddr+(sizeof(SceNetAdhocctlPeerInfoEmu)*i)+ + sizeof(SceNetAdhocctlPeerInfoEmu); + } + // Fix Last Element + if (discovered > 0) buf[discovered - 1].next = 0; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlPeerInfo); + } + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Uninitialized Library + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } int sceNetAdhocctlGetAddrByName(const char *nickName, u32 sizeAddr, u32 bufAddr) { @@ -590,7 +2255,7 @@ const HLEFunction sceNetAdhocctl[] = { {0x75ecd386, WrapI_U, "sceNetAdhocctlGetState"}, {0x8916c003, WrapI_CU, "sceNetAdhocctlGetNameByAddr"}, {0xded9d28e, WrapI_U, "sceNetAdhocctlGetParameter"}, - {0x81aee1be, WrapI_V, "sceNetAdhocctlGetScanInfo"}, + {0x81aee1be, WrapI_UU, "sceNetAdhocctlGetScanInfo"}, {0x5e7f79c9, WrapI_U, "sceNetAdhocctlJoin"}, {0x8db83fdc, WrapI_CIU, "sceNetAdhocctlGetPeerInfo"}, {0xec0635c1, WrapI_C, "sceNetAdhocctlCreate"}, @@ -601,7 +2266,7 @@ const HLEFunction sceNetAdhocctl[] = { {0x362cbe8f, WrapI_U, "sceNetAdhocctlGetAdhocId"}, {0x5a014ce0, WrapI_U, "sceNetAdhocctlGetGameModeInfo"}, {0x99560abe, WrapI_CUU, "sceNetAdhocctlGetAddrByName"}, - {0xb0b80e80, 0, "sceNetAdhocctlCreateEnterGameModeMin"}, // ?? + {0xb0b80e80, 0, "sceNetAdhocctlCreateEnterGameModeMin"}, // ?? }; const HLEFunction sceNetAdhocDiscover[] = { diff --git a/Core/HLE/sceNetAdhoc.h b/Core/HLE/sceNetAdhoc.h index 2c7c1ec89b..1529557593 100644 --- a/Core/HLE/sceNetAdhoc.h +++ b/Core/HLE/sceNetAdhoc.h @@ -24,3 +24,6 @@ void Register_sceNetAdhoc(); void __NetAdhocInit(); void __NetAdhocShutdown(); void __NetAdhocDoState(PointerWrap &p); + +// I have to call this from netdialog +int sceNetAdhocctlCreate(const char * groupName); diff --git a/Core/HLE/sceNp.cpp b/Core/HLE/sceNp.cpp index 7a3dcc0bcc..48e603491c 100644 --- a/Core/HLE/sceNp.cpp +++ b/Core/HLE/sceNp.cpp @@ -46,9 +46,22 @@ void Register_sceNp() RegisterModule("sceNp", ARRAY_SIZE(sceNp), sceNp); } +int sceNpAuth_4EC1F667() +{ + // No parameters + ERROR_LOG(HLE, "UNIMPL sceNpAuth_4EC1F667()"); + return 0; +} + +int sceNpAuth_A1DE86F8(u32 poolSize, u32 stackSize, u32 threadPrio) +{ + ERROR_LOG(HLE, "UNIMPL sceNpAuth_A1DE86F8(%08x, %08x, %08x)",poolSize, stackSize, threadPrio); + return 0; +} + const HLEFunction sceNpAuth[] = { - {0x4EC1F667, 0, "sceNpAuth_4EC1F667"}, - {0xA1DE86F8, 0, "sceNpAuth_A1DE86F8"}, + {0x4EC1F667, &WrapI_V, "sceNpAuth_4EC1F667"}, + {0xA1DE86F8, &WrapI_UUU, "sceNpAuth_A1DE86F8"}, }; void Register_sceNpAuth() @@ -56,9 +69,22 @@ void Register_sceNpAuth() RegisterModule("sceNpAuth", ARRAY_SIZE(sceNpAuth), sceNpAuth); } +int sceNpService_00ACFAC3() +{ + // No parameters + ERROR_LOG(HLE, "UNIMPL sceNpService_00ACFAC3()"); + return 0; +} + +int sceNpService_0F8F5821(u32 poolSize, u32 stackSize, u32 threadPrio) +{ + ERROR_LOG(HLE, "UNIMPL sceNpService_0F8F5821(%08x, %08x, %08x)",poolSize, stackSize, threadPrio); + return 0; +} + const HLEFunction sceNpService[] = { - {0x00ACFAC3, 0, "sceNpService_00ACFAC3"}, - {0x0F8F5821, 0, "sceNpService_0F8F5821"}, + {0x00ACFAC3, &WrapI_V, "sceNpService_00ACFAC3"}, + {0x0F8F5821, &WrapI_UUU, "sceNpService_0F8F5821"}, }; void Register_sceNpService() diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index 8130ec6d57..ac068a9fdc 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -45,9 +45,6 @@ const int PSP_POWER_CB_BATTERY_FULL = 0x00000064; const int POWER_CB_AUTO = -1; -const int PSP_MODEL_FAT = 0; -const int PSP_MODEL_SLIM = 1; - const int numberOfCBPowerSlots = 16; const int numberOfCBPowerSlotsPrivate = 32; @@ -55,7 +52,7 @@ static bool volatileMemLocked; static int powerCbSlots[numberOfCBPowerSlots]; static std::vector volatileWaitingThreads; -// this should belong here on in CoreTiming? +// Should this belong here, or in CoreTiming? static int pllFreq = 222; static int busFreq = 111; @@ -412,7 +409,9 @@ int scePowerTick() { u32 IsPSPNonFat() { - return PSP_MODEL_FAT; + DEBUG_LOG(HLE, "%d=scePower_a85880d0_IsPSPNonFat()", g_Config.iPSPModel); + + return g_Config.iPSPModel; } static const HLEFunction scePower[] = { diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index e65c065edd..d5317869c2 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1019,7 +1019,7 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) u32 displaybuf = Memory::Read_U32(videoDataAddr + 4); int displaypts = Memory::Read_U32(videoDataAddr + 8); if (psmfplayer->mediaengine->stepVideo(videoPixelMode)) { - int displaybufSize = psmfplayer->mediaengine->writeVideoImage(Memory::GetPointer(displaybuf), frameWidth, videoPixelMode); + int displaybufSize = psmfplayer->mediaengine->writeVideoImage(displaybuf, frameWidth, videoPixelMode); gpu->InvalidateCache(displaybuf, displaybufSize, GPU_INVALIDATE_SAFE); } psmfplayer->psmfPlayerAvcAu.pts = psmfplayer->mediaengine->getVideoTimeStamp(); @@ -1050,7 +1050,7 @@ int scePsmfPlayerGetAudioData(u32 psmfPlayer, u32 audioDataAddr) DEBUG_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x)", psmfPlayer, audioDataAddr); if (Memory::IsValidAddress(audioDataAddr)) { Memory::Memset(audioDataAddr, 0, audioSamplesBytes); - psmfplayer->mediaengine->getAudioSamples(Memory::GetPointer(audioDataAddr)); + psmfplayer->mediaengine->getAudioSamples(audioDataAddr); } int ret = psmfplayer->mediaengine->IsNoAudioData() ? (int)ERROR_PSMFPLAYER_NO_MORE_DATA : 0; return hleDelayResult(ret, "psmfPlayer audio decode", 3000); @@ -1288,8 +1288,8 @@ const HLEFunction scePsmf[] = { {0x4E624A34, WrapU_UIU, "scePsmfGetEPWithId"}, {0x7C0E7AC3, WrapU_UUU, "scePsmfGetEPWithTimestamp"}, {0x5F457515, WrapU_UU, "scePsmfGetEPidWithTimestamp"}, - {0x43ac7dbb, 0, "scePsmf_43AC7DBB"}, - {0xde78e9fc, 0, "scePsmf_DE78E9FC"}, + {0x43ac7dbb, 0, "scePsmfGetPsmfMark"}, + {0xde78e9fc, 0, "scePsmfGetNumberOfPsmfMarks"}, }; const HLEFunction scePsmfPlayer[] = diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 1703248bb2..442272c06f 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -44,6 +44,10 @@ const u64 rtcMagicOffset = 62135596800000000ULL; // This is the # of microseconds between January 1, 0001 and January 1, 1601 (for Win32 FILETIME.) const u64 rtcFiletimeOffset = 50491123200000000ULL; +// 400 years is a convenient number, since leap days and everything cycle every 400 years. +// 400 years is in other words 20871 full weeks. +const u64 rtc400YearTicks = (u64)20871 * 7 * 24 * 3600 * 1000000ULL; + const int PSP_TIME_INVALID_YEAR = -1; const int PSP_TIME_INVALID_MONTH = -2; const int PSP_TIME_INVALID_DAY = -3; @@ -153,7 +157,7 @@ void __RtcTmToPspTime(ScePspDateTime &t, tm *val) void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks) { int numYearAdd = 0; - if(ticks < 1000000ULL) + if (ticks < 1000000ULL) { t.year = 1; t.month = 1; @@ -164,16 +168,18 @@ void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks) t.microsecond = ticks % 1000000ULL; return; } - else if(ticks < rtcMagicOffset ) + else if (ticks < rtcMagicOffset) { // Need to get a year past 1970 for gmtime // Add enough 400 year to pass over 1970. - // Each 400 year are equal - // 400 year is 20871 weeks - u64 ticks400Y = (u64)20871 * 7 * 24 * 3600 * 1000000ULL; - numYearAdd = (int) ((rtcMagicOffset - ticks) / ticks400Y + 1); - ticks += ticks400Y * numYearAdd; + numYearAdd = (int) ((rtcMagicOffset - ticks) / rtc400YearTicks + 1); + ticks += rtc400YearTicks * numYearAdd; + } + while (ticks >= rtcMagicOffset + rtc400YearTicks) + { + ticks -= rtc400YearTicks; + --numYearAdd; } time_t time = (ticks - rtcMagicOffset) / 1000000ULL; @@ -207,10 +213,22 @@ u64 __RtcPspTimeToTicks(ScePspDateTime &pt) local.tm_sec = pt.second; local.tm_isdst = 0; + s64 tickOffset = 0; + while (local.tm_year < 70) + { + tickOffset -= rtc400YearTicks; + local.tm_year += 400; + } + while (local.tm_year >= 470) + { + tickOffset += rtc400YearTicks; + local.tm_year -= 400; + } + time_t seconds = rtc_timegm(&local); u64 result = rtcMagicOffset + (u64) seconds * 1000000ULL; result += pt.microsecond; - return result; + return result + tickOffset; } bool __RtcValidatePspTime(ScePspDateTime &t) @@ -226,19 +244,21 @@ u32 sceRtcGetTickResolution() u32 sceRtcGetCurrentTick(u32 tickPtr) { - //Don't spam the log - //DEBUG_LOG(SCERTC, "sceRtcGetCurrentTick(%08x)", tickPtr); + VERBOSE_LOG(SCERTC, "sceRtcGetCurrentTick(%08x)", tickPtr); u64 curTick = __RtcGetCurrentTick(); if (Memory::IsValidAddress(tickPtr)) Memory::Write_U64(curTick, tickPtr); hleEatCycles(300); + hleReSchedule("rtc current tick"); return 0; } -u64 sceRtcGetAcculumativeTime() +u64 sceRtcGetAccumulativeTime() { - DEBUG_LOG(SCERTC, "sceRtcGetAcculumativeTime()"); + DEBUG_LOG(SCERTC, "sceRtcGetAccumulativeTime()"); + hleEatCycles(300); + hleReSchedule("rtc accumulative time"); return __RtcGetCurrentTick(); } @@ -268,6 +288,7 @@ u32 sceRtcGetCurrentClock(u32 pspTimePtr, int tz) Memory::WriteStruct(pspTimePtr, &ret); hleEatCycles(1900); + hleReSchedule("rtc current clock"); return 0; } @@ -293,6 +314,7 @@ u32 sceRtcGetCurrentClockLocalTime(u32 pspTimePtr) Memory::WriteStruct(pspTimePtr, &ret); hleEatCycles(2000); + hleReSchedule("rtc current clock local"); return 0; } @@ -365,41 +387,45 @@ u32 sceRtcGetDayOfWeek(u32 year, u32 month, u32 day) return local.tm_wday; } -u32 sceRtcGetDaysInMonth(u32 year, u32 month) +bool __RtcIsLeapYear(u32 year) { - DEBUG_LOG(SCERTC, "sceRtcGetDaysInMonth(%d, %d)", year, month); - u32 numberOfDays; - - if (year == 0 || month == 0 || month > 12) - return SCE_KERNEL_ERROR_INVALID_ARGUMENT; + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} +int __RtcDaysInMonth(u32 year, u32 month) +{ switch (month) { case 4: case 6: case 9: case 11: - numberOfDays = 30; - break; + return 30; + case 2: - if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) - numberOfDays = 29; - else - numberOfDays = 28; - break; + if (__RtcIsLeapYear(year)) + return 29; + return 28; default: - numberOfDays = 31; - break; + return 31; } +} - return numberOfDays; +u32 sceRtcGetDaysInMonth(u32 year, u32 month) +{ + DEBUG_LOG(SCERTC, "sceRtcGetDaysInMonth(%d, %d)", year, month); + + if (year == 0 || month == 0 || month > 12) + return SCE_KERNEL_ERROR_INVALID_ARGUMENT; + + return __RtcDaysInMonth(year, month); } u32 sceRtcIsLeapYear(u32 year) { DEBUG_LOG(SCERTC, "sceRtcIsLeapYear(%d)", year); - return (year % 4 == 0) && (!(year % 100 == 0) || (year % 400 == 0)); + return __RtcIsLeapYear(year) ? 1 : 0; } int sceRtcConvertLocalTimeToUTC(u32 tickLocalPtr,u32 tickUTCPtr) @@ -468,19 +494,19 @@ int sceRtcCheckValid(u32 datePtr) { return PSP_TIME_INVALID_DAY; } - else if (pt.day > 31) // TODO: Needs to check actual days in month, including leaps + else if (pt.day > __RtcDaysInMonth((s16)pt.year, (s16)pt.month)) { return PSP_TIME_INVALID_DAY; } - else if (pt.hour > 23) + else if (pt.hour < 0 || pt.hour > 23) { return PSP_TIME_INVALID_HOUR; } - else if (pt.minute > 59) + else if (pt.minute < 0 || pt.minute > 59) { return PSP_TIME_INVALID_MINUTES; } - else if (pt.second > 59) + else if (pt.second < 0 || pt.second > 59) { return PSP_TIME_INVALID_SECONDS; } @@ -749,7 +775,7 @@ int sceRtcTickAddHours(u32 destTickPtr, u32 srcTickPtr, int numHours) if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) { s64 srcTick = (s64)Memory::Read_U64(srcTickPtr); - srcTick += numHours*3600000000UL; + srcTick += numHours * 3600ULL * 1000000ULL; Memory::Write_U64(srcTick, destTickPtr); } DEBUG_LOG(SCERTC, "sceRtcTickAddMinutes(%d,%d,%d)", destTickPtr, srcTickPtr, numHours); @@ -762,7 +788,7 @@ int sceRtcTickAddDays(u32 destTickPtr, u32 srcTickPtr, int numDays) { s64 srcTick = (s64)Memory::Read_U64(srcTickPtr); - srcTick += numDays*86400000000UL; + srcTick += numDays * 86400ULL * 1000000ULL; Memory::Write_U64(srcTick, destTickPtr); } DEBUG_LOG(SCERTC, "sceRtcTickAddDays(%d,%d,%d)", destTickPtr, srcTickPtr, numDays); @@ -775,7 +801,7 @@ int sceRtcTickAddWeeks(u32 destTickPtr, u32 srcTickPtr, int numWeeks) { s64 srcTick = (s64)Memory::Read_U64(srcTickPtr); - srcTick += numWeeks*604800000000UL; + srcTick += numWeeks * 7ULL * 86400ULL * 1000000ULL; Memory::Write_U64(srcTick, destTickPtr); } DEBUG_LOG(SCERTC, "sceRtcTickAddWeeks(%d,%d,%d)", destTickPtr, srcTickPtr, numWeeks); @@ -784,79 +810,69 @@ int sceRtcTickAddWeeks(u32 destTickPtr, u32 srcTickPtr, int numWeeks) int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths) { - if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) + if (!Memory::IsValidAddress(destTickPtr) || !Memory::IsValidAddress(srcTickPtr)) { - u64 srcTick = Memory::Read_U64(srcTickPtr); - - ScePspDateTime pt; - memset(&pt, 0, sizeof(pt)); - - __RtcTicksToPspTime(pt,srcTick); - if(((pt.year-1)*12+pt.month) + numMonths < 1 || ((pt.year-1)*12+pt.month) + numMonths > 9999*12) - { - srcTick = 0; - } - else - { - if(numMonths < 0) - { - pt.year += numMonths/12; - int restMonth = pt.month + numMonths%12; - if(restMonth < 1) - { - pt.month = 12+restMonth; - pt.year--; - } - else - { - pt.month = restMonth; - } - } - else - { - pt.year += numMonths/12; - pt.month += numMonths%12; - if(pt.month > 12) - { - pt.month -= 12; - pt.year++; - } - } - u64 yearTicks = __RtcPspTimeToTicks(pt); - srcTick =yearTicks; - } - Memory::Write_U64(srcTick, destTickPtr); + WARN_LOG(SCERTC, "sceRtcTickAddMonths(%08x, %08x, %d): invalid address", destTickPtr, srcTickPtr, numMonths); + return -1; } - DEBUG_LOG(SCERTC, "sceRtcTickAddMonths(%d,%d,%d)", destTickPtr, srcTickPtr, numMonths); + u64 srcTick = Memory::Read_U64(srcTickPtr); + + ScePspDateTime pt; + memset(&pt, 0, sizeof(pt)); + + __RtcTicksToPspTime(pt,srcTick); + pt.year += numMonths / 12; + pt.month += numMonths % 12; + + if (pt.month < 1) + { + pt.month += 12; + pt.year--; + } + if (pt.month > 12) + { + pt.month -= 12; + pt.year++; + } + + if (__RtcValidatePspTime(pt)) + { + // Did we land on a year that isn't a leap year? + if (pt.month == 2 && pt.day == 29 && !__RtcIsLeapYear((s16)pt.year)) + pt.day = 28; + Memory::Write_U64(__RtcPspTimeToTicks(pt), destTickPtr); + } + + DEBUG_LOG(SCERTC, "sceRtcTickAddMonths(%08x, %08x = %lld, %d)", destTickPtr, srcTickPtr, srcTick, numMonths); return 0; } int sceRtcTickAddYears(u32 destTickPtr, u32 srcTickPtr, int numYears) { - if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) + if (!Memory::IsValidAddress(destTickPtr) || !Memory::IsValidAddress(srcTickPtr)) { - u64 srcTick = Memory::Read_U64(srcTickPtr); - - ScePspDateTime pt; - memset(&pt, 0, sizeof(pt)); - - __RtcTicksToPspTime(pt,srcTick); - if(pt.year + numYears <= 0 || pt.year + numYears > 9999) - { - srcTick = 0; - } - else - { - pt.year += numYears; - u64 yearTicks = __RtcPspTimeToTicks(pt); - srcTick =yearTicks; - } - - Memory::Write_U64(srcTick, destTickPtr); + WARN_LOG(SCERTC, "sceRtcTickAddYears(%08x, %08x, %d): invalid address", destTickPtr, srcTickPtr, numYears); + return -1; } - DEBUG_LOG(SCERTC, "sceRtcTickAddYears(%d,%d,%d)", destTickPtr, srcTickPtr, numYears); + u64 srcTick = Memory::Read_U64(srcTickPtr); + + ScePspDateTime pt; + memset(&pt, 0, sizeof(pt)); + + __RtcTicksToPspTime(pt, srcTick); + pt.year += numYears; + + if (__RtcValidatePspTime(pt)) + { + // Did we land on a year that isn't a leap year? + if (pt.month == 2 && pt.day == 29 && !__RtcIsLeapYear((s16)pt.year)) + pt.day = 28; + Memory::Write_U64(__RtcPspTimeToTicks(pt), destTickPtr); + } + + DEBUG_LOG(SCERTC, "sceRtcTickAddYears(%08x, %08x = %lld, %d)", destTickPtr, srcTickPtr, srcTick, numYears); return 0; } @@ -886,8 +902,8 @@ const HLEFunction sceRtc[] = { {0xC41C2853, &WrapU_V, "sceRtcGetTickResolution"}, {0x3f7ad767, &WrapU_U, "sceRtcGetCurrentTick"}, - {0x011F03C1, &WrapU64_V, "sceRtcGetAccumulativeTime"}, - {0x029CA3B3, &WrapU64_V, "sceRtcGetAccumlativeTime"}, + {0x011F03C1, &WrapU64_V, "sceRtcGetAccumulativeTime"}, + {0x029CA3B3, &WrapU64_V, "sceRtcGetAccumlativeTime"}, {0x4cfa57b0, &WrapU_UI, "sceRtcGetCurrentClock"}, {0xE7C27D1B, &WrapU_U, "sceRtcGetCurrentClockLocalTime"}, {0x34885E0D, &WrapI_UU, "sceRtcConvertUtcToLocalTime"}, @@ -925,7 +941,7 @@ const HLEFunction sceRtc[] = {0x62685E98, &WrapI_U, "sceRtcGetLastAdjustedTime"}, {0x203ceb0d, 0, "sceRtcGetLastReincarnatedTime"}, {0x7d1fbed3, &WrapI_UU, "sceRtcSetAlarmTick"}, - {0xf5fcc995, 0, "sceRtc_F5FCC995"}, + {0xf5fcc995, 0, "sceRtcGetCurrentNetworkTick"}, {0x81fcda34, 0, "sceRtcIsAlarmed"}, {0xfb3b18cd, 0, "sceRtcRegisterCallback"}, {0x6a676d2d, 0, "sceRtcUnregisterCallback"}, diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 01a9b5827b..6bf970ba9a 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -25,6 +25,12 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/KernelWaitHelpers.h" +#include "Core/FileSystems/BlockDevices.h" +#include "Core/FileSystems/ISOFileSystem.h" +#include "Core/FileSystems/VirtualDiscFileSystem.h" + +#include "file/file_util.h" + const u64 MICRO_DELAY_ACTIVATE = 4000; static u8 umdActivated = 1; @@ -36,6 +42,8 @@ static int umdStatChangeEvent = -1; static std::vector umdWaitingThreads; static std::map umdPausedWaits; +bool UMDReplacePermit = false; + struct PspUmdInfo { u32_le size; u32_le type; @@ -60,7 +68,7 @@ void __UmdInit() void __UmdDoState(PointerWrap &p) { - auto s = p.Section("sceUmd", 1); + auto s = p.Section("sceUmd", 1, 2); if (!s) return; @@ -74,6 +82,9 @@ void __UmdDoState(PointerWrap &p) CoreTiming::RestoreRegisterEvent(umdStatChangeEvent, "UmdChange", __UmdStatChange); p.Do(umdWaitingThreads); p.Do(umdPausedWaits); + + if (s > 1) + p.Do(UMDReplacePermit); } u8 __KernelUmdGetState() @@ -266,7 +277,6 @@ u32 sceUmdRegisterUMDCallBack(u32 cbId) // There's only ever one. driveCBId = cbId; } - DEBUG_LOG(SCEIO, "%d=sceUmdRegisterUMDCallback(id=%08x)", retVal, cbId); return retVal; } @@ -281,7 +291,6 @@ int sceUmdUnRegisterUMDCallBack(int cbId) retVal = cbId; driveCBId = -1; } - DEBUG_LOG(SCEIO, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId); return retVal; } @@ -436,14 +445,48 @@ u32 sceUmdGetErrorStat() return umdErrorStat; } +void __UmdReplace(std::string filepath) { + // Only get system from disc0 seems have been enough. + IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); + if (!currentUMD) + return; + + IFileSystem* umd2; + FileInfo info; + if (!getFileInfo(filepath.c_str(), &info)) // This shouldn't happen, but for safety. + return; + if (info.isDirectory) { + umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath); + } else { + auto bd = constructBlockDevice(filepath.c_str()); + if (!bd) + return; + umd2 = new ISOFileSystem(&pspFileSystem, bd); + + pspFileSystem.Remount(currentUMD, umd2); + } + delete currentUMD; + + // TODO Is this always correct if UMD was not activated? + u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; + if (driveCBId != -1) + __KernelNotifyCallback(driveCBId, notifyArg); +} + +bool getUMDReplacePermit() { + return UMDReplacePermit; +} + u32 sceUmdReplaceProhibit() { + UMDReplacePermit = false; DEBUG_LOG(SCEIO,"sceUmdReplaceProhibit()"); return 0; } u32 sceUmdReplacePermit() { + UMDReplacePermit = true; DEBUG_LOG(SCEIO,"sceUmdReplacePermit()"); return 0; } @@ -464,8 +507,8 @@ const HLEFunction sceUmdUser[] = {0xBD2BDE07,&WrapI_I,"sceUmdUnRegisterUMDCallBack"}, {0x87533940,WrapU_V,"sceUmdReplaceProhibit"}, {0xCBE9F02A,WrapU_V,"sceUmdReplacePermit"}, - {0x14c6c45c,0,"sceUmdUser_14C6C45C"}, - {0xb103fa38,0,"sceUmdUser_B103FA38"}, + {0x14c6c45c,0,"sceUmdUnuseUMDInMsUsbWlan"}, + {0xb103fa38,0,"sceUmdUseUMDInMsUsbWlan"}, }; void Register_sceUmdUser() diff --git a/Core/HLE/sceUmd.h b/Core/HLE/sceUmd.h index 3423c88f4c..246d6384b2 100644 --- a/Core/HLE/sceUmd.h +++ b/Core/HLE/sceUmd.h @@ -41,4 +41,7 @@ enum pspUmdType { void __UmdInit(); void __UmdDoState(PointerWrap &p); +void __UmdReplace(std::string filepath); +bool getUMDReplacePermit(); + void Register_sceUmdUser(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index ed1f21b954..f5c8a952d3 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -580,19 +580,15 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) break; case PSP_SYSTEMPARAM_ID_INT_DATE_FORMAT: param = g_Config.iDateFormat; - INFO_LOG_REPORT(SCEUTILITY, "sceUtilitySystemGetSystemParamInt: %s", "Date Format") break; case PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT: param = g_Config.iTimeFormat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR; - INFO_LOG_REPORT(SCEUTILITY, "sceUtilitySystemGetSystemParamInt: %s", "Time Format") break; case PSP_SYSTEMPARAM_ID_INT_TIMEZONE: param = g_Config.iTimeZone; - INFO_LOG_REPORT(SCEUTILITY, "sceUtilitySystemGetSystemParamInt: %s", "Timezone") break; case PSP_SYSTEMPARAM_ID_INT_DAYLIGHTSAVINGS: param = g_Config.bDayLightSavings?PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_SAVING:PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD; - INFO_LOG_REPORT(SCEUTILITY, "sceUtilitySystemGetSystemParamInt: %s", "Daylight Savings"); break; case PSP_SYSTEMPARAM_ID_INT_LANGUAGE: param = g_Config.iLanguage; @@ -602,7 +598,6 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) break; case PSP_SYSTEMPARAM_ID_INT_LOCK_PARENTAL_LEVEL: param = g_Config.iLockParentalLevel; - INFO_LOG_REPORT(SCEUTILITY, "sceUtilitySystemGetSystemParamInt: %s", "Lock Parental Level"); break; default: return PSP_SYSTEMPARAM_RETVAL_FAIL; @@ -807,15 +802,16 @@ const HLEFunction sceUtility[] = {0xdb4149ee, 0, "sceUtility_DB4149EE"}, {0xcfe7c460, 0, "sceUtility_CFE7C460"}, - {0xc130d441, 0, "sceUtility_C130D441"}, - {0x0940a1b9, 0, "sceUtility_0940A1B9"}, - {0x094198b8, 0, "sceUtility_094198B8"}, - {0xa7bb7c67, 0, "sceUtility_A7BB7C67"}, + {0xc130d441, 0, "sceUtilityPsnShutdownStart"}, + {0xa7bb7c67, 0, "sceUtilityPsnInitStart"}, + {0x0940a1b9, 0, "sceUtilityPsnUpdate"}, + {0x094198b8, 0, "sceUtilityPsnGetStatus"}, - {0x3a15cd0a, 0, "sceUtility_3A15CD0A"}, - {0x9f313d14, 0, "sceUtility_9F313D14"}, - {0xd23665f4, 0, "sceUtility_D23665F4"}, - {0xd4c2bd73, 0, "sceUtility_D4C2BD73"}, + {0x9f313d14, 0, "sceUtilityAutoConnectShutdownStart"}, + {0x3a15cd0a, 0, "sceUtilityAutoConnectInitStart"}, + {0xd23665f4, 0, "sceUtilityAutoConnectUpdate"}, + {0xd4c2bd73, 0, "sceUtilityAutoConnectGetStatus"}, + {0x0e0c27af, 0, "sceUtilityAutoConnectAbort"}, {0x06A48659, 0, "sceUtilityRssSubscriberShutdownStart"}, {0x4B0A8FE5, 0, "sceUtilityRssSubscriberInitStart"}, @@ -842,8 +838,6 @@ const HLEFunction sceUtility[] = {0x70267adf, 0, "sceUtility_70267ADF"}, {0xece1d3e5, 0, "sceUtility_ECE1D3E5"}, {0xef3582b2, 0, "sceUtility_EF3582B2"}, - - {0x0e0c27af, 0, "sceUtility_0E0C27AF"}, }; void Register_sceUtility() diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index b182179bd9..9a84e1b8e0 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -97,7 +97,7 @@ const HLEFunction sceVaudio[] = { {0x346FBE94, WrapU_II, "sceVaudioSetEffectType"}, {0xCBD4AC51, WrapU_I, "sceVaudioSetAlcMode"}, {0x504e4745, 0, "sceVaudio_504E4745"}, - {0x27acc20b, 0, "sceVaudio_27ACC20B"}, + {0x27acc20b, 0, "sceVaudioChReserveBuffering"}, {0xe8e78dc8, 0, "sceVaudio_E8E78DC8"}, }; diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 52c1a27da9..a933ea83f0 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -60,24 +60,6 @@ static AVPixelFormat getSwsFormat(int pspFormat) return (AVPixelFormat)0; } } -#endif - -static int getPixelFormatBytes(int pspFormat) -{ - switch (pspFormat) - { - case TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650: - case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR5551: - case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR4444: - return 2; - case TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888: - return 4; - - default: - ERROR_LOG(ME, "Unknown pixel format"); - return 4; - } -} void ffmpeg_logger(void *, int level, const char *format, va_list va_args) { // We're still called even if the level doesn't match. @@ -113,6 +95,24 @@ bool InitFFmpeg() { return true; } +#endif + +static int getPixelFormatBytes(int pspFormat) +{ + switch (pspFormat) + { + case TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650: + case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR5551: + case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR4444: + return 2; + case TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888: + return 4; + + default: + ERROR_LOG(ME, "Unknown pixel format"); + return 4; + } +} void __AdjustBGMVolume(s16 *samples, u32 count) { if (g_Config.iBGMVolume < 0 || g_Config.iBGMVolume >= MAX_CONFIG_VOLUME) { @@ -126,11 +126,13 @@ void __AdjustBGMVolume(s16 *samples, u32 count) { } MediaEngine::MediaEngine(): m_pdata(0) { +#ifdef USE_FFMPEG m_pFormatCtx = 0; m_pCodecCtx = 0; m_pFrame = 0; m_pFrameRGB = 0; m_pIOContext = 0; +#endif m_videoStream = -1; m_audioStream = -1; m_buffer = 0; @@ -170,11 +172,13 @@ void MediaEngine::closeMedia() { if (m_demux) delete m_demux; m_buffer = 0; +#ifdef USE_FFMPEG m_pFrame = 0; m_pFrameRGB = 0; m_pIOContext = 0; m_pCodecCtx = 0; m_pFormatCtx = 0; +#endif m_pdata = 0; m_demux = 0; AT3Close(&m_audioContext); @@ -198,7 +202,11 @@ void MediaEngine::DoState(PointerWrap &p){ p.Do(hasloadStream); if (hasloadStream && p.mode == p.MODE_READ) loadStream(m_mpegheader, 2048, m_ringbuffersize); +#ifdef USE_FFMPEG u32 hasopencontext = m_pFormatCtx != NULL; +#else + u32 hasopencontext = false; +#endif p.Do(hasopencontext); if (hasopencontext && p.mode == p.MODE_READ) openContext(); @@ -325,22 +333,25 @@ int MediaEngine::addStreamData(u8* buffer, int addSize) { m_demux->demux(m_audioStream); } #ifdef USE_FFMPEG - if (!m_pFormatCtx) { + if (!m_pFormatCtx && m_pdata->getQueueSize() >= 2048 * 6) { m_pdata->get_front(m_mpegheader, sizeof(m_mpegheader)); int mpegoffset = bswap32(*(int*)(m_mpegheader + 8)); m_pdata->pop_front(0, mpegoffset); openContext(); } #endif // USE_FFMPEG + + // We added data, so... not the end anymore? + m_isVideoEnd = false; } return size; } bool MediaEngine::setVideoDim(int width, int height) { +#ifdef USE_FFMPEG if (!m_pCodecCtx) return false; -#ifdef USE_FFMPEG if (width == 0 && height == 0) { // use the orignal video size @@ -487,10 +498,18 @@ inline void writeVideoLineABGR4444(void *destp, const void *srcp, int width) { } } -int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) { +int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMode) { + if (!Memory::IsValidAddress(bufferPtr) || frameWidth > 2048) { + // Clearly invalid values. Let's just not. + ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth); + return false; + } + + u8 *buffer = Memory::GetPointer(bufferPtr); + +#ifdef USE_FFMPEG if ((!m_pFrame)||(!m_pFrameRGB)) return false; -#ifdef USE_FFMPEG int videoImageSize = 0; // lock the image size int height = m_desHeight; @@ -536,7 +555,7 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) break; default: - ERROR_LOG(ME, "Unsupported video pixel format %d", videoPixelMode); + ERROR_LOG_REPORT(ME, "Unsupported video pixel format %d", videoPixelMode); break; } return videoImageSize; @@ -544,11 +563,19 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) return 0; } -int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoPixelMode, +int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int videoPixelMode, int xpos, int ypos, int width, int height) { + if (!Memory::IsValidAddress(bufferPtr) || frameWidth > 2048) { + // Clearly invalid values. Let's just not. + ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth); + return false; + } + + u8 *buffer = Memory::GetPointer(bufferPtr); + +#ifdef USE_FFMPEG if ((!m_pFrame)||(!m_pFrameRGB)) return false; -#ifdef USE_FFMPEG int videoImageSize = 0; // lock the image size u8 *imgbuf = buffer; @@ -610,7 +637,11 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP } u8 *MediaEngine::getFrameImage() { +#ifdef USE_FFMPEG return m_pFrameRGB->data[0]; +#else + return NULL; +#endif } int MediaEngine::getRemainSize() { @@ -619,7 +650,12 @@ int MediaEngine::getRemainSize() { return std::max(m_pdata->getRemainSize() - m_decodingsize - 2048, 0); } -int MediaEngine::getAudioSamples(u8* buffer) { +int MediaEngine::getAudioSamples(u32 bufferPtr) { + if (!Memory::IsValidAddress(bufferPtr)) { + ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); + } + + u8 *buffer = Memory::GetPointer(bufferPtr); if (!m_demux) { return 0; } diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index 0005a9c8d4..970d1a4dc7 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -19,7 +19,6 @@ // Simulation of the hardware video/audio decoders. // The idea is high level emulation where we simply use FFMPEG. -// TODO: Actually hook up to ffmpeg. #pragma once @@ -32,18 +31,22 @@ struct SimpleAT3; +#ifdef USE_FFMPEG struct SwsContext; struct AVFrame; struct AVIOContext; struct AVFormatContext; struct AVCodecContext; +#endif inline s64 getMpegTimeStamp(u8* buf) { return (s64)buf[5] | ((s64)buf[4] << 8) | ((s64)buf[3] << 16) | ((s64)buf[2] << 24) | ((s64)buf[1] << 32) | ((s64)buf[0] << 36); } +#ifdef USE_FFMPEG bool InitFFmpeg(); +#endif void __AdjustBGMVolume(s16 *samples, u32 count); @@ -68,10 +71,10 @@ public: int getRemainSize(); bool stepVideo(int videoPixelMode); - int writeVideoImage(u8* buffer, int frameWidth = 512, int videoPixelMode = 3); - int writeVideoImageWithRange(u8* buffer, int frameWidth, int videoPixelMode, + int writeVideoImage(u32 bufferPtr, int frameWidth = 512, int videoPixelMode = 3); + int writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int videoPixelMode, int xpos, int ypos, int width, int height); - int getAudioSamples(u8* buffer); + int getAudioSamples(u32 bufferPtr); bool setVideoDim(int width = 0, int height = 0); s64 getVideoTimeStamp(); @@ -89,12 +92,15 @@ private: public: // TODO: Very little of this below should be public. // Video ffmpeg context - not used for audio +#ifdef USE_FFMPEG AVFormatContext *m_pFormatCtx; AVCodecContext *m_pCodecCtx; AVFrame *m_pFrame; AVFrame *m_pFrameRGB; AVIOContext *m_pIOContext; SwsContext *m_sws_ctx; +#endif + int m_sws_fmt; u8 *m_buffer; int m_videoStream; diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 149c07d679..328e952c28 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -387,7 +387,7 @@ void SasInstance::MixVoice(SasVoice &voice) { case VOICETYPE_PCM: if (voice.type == VOICETYPE_PCM && !voice.pcmAddr) break; - default: + default: // Load resample history (so we can use a wide filter) resampleBuffer[0] = voice.resampleHist[0]; resampleBuffer[1] = voice.resampleHist[1]; @@ -664,8 +664,7 @@ static const short expCurve[] = { 0x7000 }; -static int durationFromRate(int rate) -{ +static int durationFromRate(int rate) { if (rate == 0) { return PSP_SAS_ENVELOPE_FREQ_MAX; } else { @@ -686,16 +685,16 @@ static int durationFromRate(int rate) const short expCurveReference = 0x7000; +const float expCurveToEnvelopeHeight = (float)PSP_SAS_ENVELOPE_HEIGHT_MAX / (float)expCurveReference; + // This needs a rewrite / rethink. Doing all this per sample is insane. -static int getExpCurveAt(int index, int duration) { - const short curveLength = sizeof(expCurve) / sizeof(short); +static float computeExpCurveAt(int index, float invDuration) { + const int curveLength = ARRAY_SIZE(expCurve); - if (duration == 0) { - // Avoid division by zero, and thus undefined behaviour in conversion to int. - return 0; - } + if (invDuration == 0.0f) + return 0.0f; - float curveIndex = (index * curveLength) / (float) duration; + float curveIndex = (index * curveLength) * invDuration; int curveIndex1 = (int) curveIndex; int curveIndex2 = curveIndex1 + 1; float curveIndexFraction = curveIndex - curveIndex1; @@ -706,12 +705,11 @@ static int getExpCurveAt(int index, int duration) { return expCurve[curveLength - 1]; } - float sample = expCurve[curveIndex1] * (1.f - curveIndexFraction) + expCurve[curveIndex2] * curveIndexFraction; - return (short)(sample); + return expCurve[curveIndex1] * (1.f - curveIndexFraction) + expCurve[curveIndex2] * curveIndexFraction; } ADSREnvelope::ADSREnvelope() - : attackRate(0), + : attackRate(0), decayRate(0), sustainRate(0), releaseRate(0), @@ -722,45 +720,44 @@ ADSREnvelope::ADSREnvelope() releaseType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE), state_(STATE_OFF), steps_(0), - height_(0) { + height_(0), + type_(0), + rate_(0), + invDuration_(0) { } -void ADSREnvelope::WalkCurve(int rate, int type) { - short expFactor; - int duration; +void ADSREnvelope::WalkCurve(int type) { + float expFactor; switch (type) { case PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE: - height_ += rate; + height_ += rate_; break; case PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE: - height_ -= rate; + height_ -= rate_; break; case PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT: if (height_ < (s64)PSP_SAS_ENVELOPE_HEIGHT_MAX * 3 / 4) { - height_ += rate; + height_ += rate_; } else { - height_ += rate / 4; + height_ += rate_ / 4; } break; case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: - // NOTICE_LOG(SAS, "UNIMPL EXP DECR"); - duration = durationFromRate(rate); - expFactor = getExpCurveAt(steps_, duration); - height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference; + expFactor = computeExpCurveAt(steps_, invDuration_); + height_ = (s64)(expFactor * expCurveToEnvelopeHeight); height_ = PSP_SAS_ENVELOPE_HEIGHT_MAX - height_; break; case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: - duration = durationFromRate(rate); - expFactor = getExpCurveAt(steps_, duration); - height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference; + expFactor = computeExpCurveAt(steps_, invDuration_); + height_ = (s64)(expFactor * expCurveToEnvelopeHeight); break; case PSP_SAS_ADSR_CURVE_MODE_DIRECT: - height_ = rate; // Simple :) + height_ = rate_; // Simple :) break; } } @@ -768,29 +765,65 @@ void ADSREnvelope::WalkCurve(int rate, int type) { void ADSREnvelope::SetState(ADSRState state) { steps_ = 0; state_ = state; + switch (state) { + case STATE_ATTACK: + rate_ = attackRate; + type_ = attackType; + break; + case STATE_DECAY: + rate_ = decayRate; + type_ = decayType; + break; + case STATE_SUSTAIN: + rate_ = sustainRate; + type_ = sustainType; + break; + case STATE_RELEASE: + rate_ = releaseRate; + type_ = releaseType; + break; + case STATE_OFF: + return; + } + + switch (type_) { + case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: + case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: + { + int duration = durationFromRate(rate_); + if (duration == 0) { + invDuration_ = 0.0f; + } else { + invDuration_ = 1.0f / (float)duration; + } + } + break; + default: + break; + } } void ADSREnvelope::Step() { switch (state_) { case STATE_ATTACK: - WalkCurve(attackRate, attackType); + WalkCurve(type_); if (height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX || height_ < 0) SetState(STATE_DECAY); break; case STATE_DECAY: - WalkCurve(decayRate, decayType); + WalkCurve(type_); if (height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX || height_ < sustainLevel) SetState(STATE_SUSTAIN); break; case STATE_SUSTAIN: - WalkCurve(sustainRate, sustainType); + WalkCurve(type_); if (height_ <= 0) { height_ = 0; SetState(STATE_RELEASE); } break; case STATE_RELEASE: - WalkCurve(releaseRate, releaseType); + WalkCurve(type_); if (height_ <= 0) { height_ = 0; SetState(STATE_OFF); @@ -810,13 +843,16 @@ void ADSREnvelope::KeyOn() { void ADSREnvelope::KeyOff() { SetState(STATE_RELEASE); + // Does this really make sense? I don't think so, the release-decay should happen + // from whatever level we are at, although the weirdo exponentials we have start at a fixed state :( height_ = sustainLevel; } void ADSREnvelope::DoState(PointerWrap &p) { auto s = p.Section("ADSREnvelope", 1); - if (!s) + if (!s) { return; + } p.Do(attackRate); p.Do(decayRate); @@ -830,4 +866,9 @@ void ADSREnvelope::DoState(PointerWrap &p) { p.Do(state_); p.Do(steps_); p.Do(height_); + + // If loading, recompute the per-state variables + if (p.GetMode() == PointerWrap::MODE_READ) { + SetState(state_); + } } diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index d4ff3af1c8..b438cab737 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -140,7 +140,7 @@ public: ADSREnvelope(); void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2); - void WalkCurve(int rate, int type); + void WalkCurve(int type); void KeyOn(); void KeyOff(); @@ -166,6 +166,14 @@ public: void DoState(PointerWrap &p); private: + void ComputeDuration(); + + // Internal variables that are recomputed on state changes + // No need to save in state + int rate_; + int type_; + float invDuration_; + enum ADSRState { STATE_ATTACK, STATE_DECAY, diff --git a/Core/Host.h b/Core/Host.h index 0031215158..44bc33e791 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -75,12 +75,6 @@ public: virtual bool CanCreateShortcut() {return false;} virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;} -#ifdef _WIN32 - // Implement this on your platform to grab text input from the user for whatever purpose. - virtual bool InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outlength) { return false; } - virtual bool InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { return false; } -#endif - // Used for headless. virtual bool ShouldSkipUI() { return false; } virtual void SendDebugOutput(const std::string &output) {} diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 1e234580ad..3e938dae21 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -129,7 +129,7 @@ IdentifiedFileType Identify_File(std::string &filename) if (id == 'FLE\x7F') { // There are a few elfs misnamed as pbp (like Trig Wars), accept that. if (!strcasecmp(extension.c_str(), ".plf") || strstr(filename.c_str(),"BOOT.BIN") || - !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") || + !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") || !strcasecmp(extension.c_str(), ".pbp")) { return FILETYPE_PSP_ELF; } @@ -173,7 +173,6 @@ IdentifiedFileType Identify_File(std::string &filename) } bool LoadFile(std::string &filename, std::string *error_string) { - INFO_LOG(LOADER,"Identifying file..."); // Note that this can modify filename! switch (Identify_File(filename)) { case FILETYPE_PSP_PBP_DIRECTORY: diff --git a/Core/MIPS/ARM/ArmAsm.cpp b/Core/MIPS/ARM/ArmAsm.cpp index 7e58457222..0a2174f102 100644 --- a/Core/MIPS/ARM/ArmAsm.cpp +++ b/Core/MIPS/ARM/ArmAsm.cpp @@ -31,12 +31,7 @@ using namespace ArmGen; //static int temp32; // unused? -//TODO - make an option -//#if _DEBUG -static bool enableDebug = false; -//#else -// bool enableDebug = false; -//#endif +static const bool enableDebug = false; //static bool enableStatistics = false; //unused? @@ -49,13 +44,13 @@ static bool enableDebug = false; // r4 to r11: used to hold local variables. // r0 to r3: used to hold argument values passed to a subroutine, and also hold results returned from a subroutine. -// R2, R3, R4, R5, R6, R7, R8, R10, R11 // omitting R9? - +// Mappable registers: +// R2, R3, R4, R5, R6, R8, R11 // STATIC ALLOCATION ARM: -// R11 : Memory base pointer. // R10 : MIPS state -// R9 : +// R11 : Memory base pointer. +// R7 : Down counter extern volatile CoreState coreState; void JitAt() @@ -63,14 +58,6 @@ void JitAt() MIPSComp::jit->Compile(currentMIPS->pc); } -/* -double testD; - -u32 DoubleTest(u32 sp) { - volatile double local = 1.0; - testD += local; - return (u32)(&local); -} void ShowPC(u32 sp) { if (currentMIPS) { @@ -78,7 +65,7 @@ void ShowPC(u32 sp) { } else { ERROR_LOG(JIT, "Universe corrupt?"); } -}*/ +} void DisassembleArm(const u8 *data, int size); @@ -92,7 +79,7 @@ void Jit::GenerateFixedCode() { enterCode = AlignCode16(); - INFO_LOG(JIT, "Base: %08x", (u32)Memory::base); + DEBUG_LOG(JIT, "Base: %08x", (u32)Memory::base); SetCC(CC_AL); @@ -139,6 +126,7 @@ void Jit::GenerateFixedCode() FixupBranch skipToRealDispatch2 = B(); //skip the sync and compare first time dispatcherPCInR0 = GetCodePtr(); + // TODO: Do we always need to write PC to RAM here? MovToPC(R0); // At this point : flags = EQ. Fine for the next check, no need to jump over it. @@ -154,12 +142,15 @@ void Jit::GenerateFixedCode() dispatcherNoCheck = GetCodePtr(); // Debug - // MOV(R0, R13); - // QuickCallFunction(R1, (void *)&ShowPC); + if (enableDebug) { + MOV(R0, R13); + QuickCallFunction(R1, (void *)&ShowPC); + } LDR(R0, CTXREG, offsetof(MIPSState, pc)); + // TODO: In practice, do we ever run code from uncached space (| 0x40000000)? If not, we can remove this BIC. BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); AND(R1, R0, Operand2(0xFC, 4)); // rotation is to the right, in 2-bit increments. BIC(R0, R0, Operand2(0xFC, 4)); CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 4)); @@ -175,7 +166,7 @@ void Jit::GenerateFixedCode() B(R0); SetCC(CC_AL); - //Ok, no block, let's jit + // No block found, let's jit SaveDowncount(); QuickCallFunction(R2, (void *)&JitAt); RestoreDowncount(); diff --git a/Core/MIPS/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index 66499cef44..41063e109b 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -543,12 +543,12 @@ namespace MIPSComp } gpr.MapDirtyIn(rt, rs); - if (cpu_info.bArmV7) { - UBFX(gpr.R(rt), gpr.R(rs), pos, size); - } else { - MOV(gpr.R(rt), Operand2(gpr.R(rs), ST_LSR, pos)); - ANDI2R(gpr.R(rt), gpr.R(rt), mask, R0); - } +#ifdef HAVE_ARMV7 + UBFX(gpr.R(rt), gpr.R(rs), pos, size); +#else + MOV(gpr.R(rt), Operand2(gpr.R(rs), ST_LSR, pos)); + ANDI2R(gpr.R(rt), gpr.R(rt), mask, R0); +#endif break; case 0x4: //ins @@ -564,16 +564,18 @@ namespace MIPSComp gpr.MapReg(rt, MAP_DIRTY); ANDI2R(gpr.R(rt), gpr.R(rt), destmask, R0); - ORI2R(gpr.R(rt), gpr.R(rt), inserted, R0); + if (inserted != 0) { + ORI2R(gpr.R(rt), gpr.R(rt), inserted, R0); + } } else { gpr.MapDirtyIn(rt, rs, false); - if (cpu_info.bArmV7) { - BFI(gpr.R(rt), gpr.R(rs), pos, size-pos); - } else { - ANDI2R(R0, gpr.R(rs), sourcemask, R1); - ANDI2R(gpr.R(rt), gpr.R(rt), destmask, R1); - ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, pos)); - } +#ifdef HAVE_ARMV7 + BFI(gpr.R(rt), gpr.R(rs), pos, size-pos); +#else + ANDI2R(R0, gpr.R(rs), sourcemask, R1); + ANDI2R(gpr.R(rt), gpr.R(rt), destmask, R1); + ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, pos)); +#endif } } break; @@ -621,12 +623,12 @@ namespace MIPSComp return; } - if (cpu_info.bArmV7) { - gpr.MapDirtyIn(rd, rt); - RBIT(gpr.R(rd), gpr.R(rt)); - } else { - Comp_Generic(op); - } +#ifdef HAVE_ARMV7 + gpr.MapDirtyIn(rd, rt); + RBIT(gpr.R(rd), gpr.R(rt)); +#else + Comp_Generic(op); +#endif break; default: Comp_Generic(op); @@ -763,7 +765,11 @@ namespace MIPSComp denominator >>= 1; } // The shift value is one too much for the divide by the same value. - LSR(gpr.R(MIPS_REG_LO), gpr.R(rs), shift - 1); + if (shift > 1) { + LSR(gpr.R(MIPS_REG_LO), gpr.R(rs), shift - 1); + } else { + MOV(gpr.R(MIPS_REG_LO), gpr.R(rs)); + } } } else if (cpu_info.bIDIVa) { // TODO: Does this handle INT_MAX, 0, etc. correctly? @@ -777,12 +783,10 @@ namespace MIPSComp gpr.MapDirtyDirtyInIn(MIPS_REG_LO, MIPS_REG_HI, rs, rt); MOV(R0, gpr.R(rt)); + FixupBranch skipper; if (!skipZero) { CMP(gpr.R(rt), 0); - SetCC(CC_EQ); - // Just set to a really high number, can't divide by zero. - MVN(R0, 0); - SetCC(CC_AL); + skipper = B_CC(CC_EQ); } // Double R0 until it would be (but isn't) bigger than the numerator. @@ -811,12 +815,12 @@ namespace MIPSComp // We didn't change rt. If it was 0, then clear HI and LO. if (!skipZero) { - CMP(gpr.R(rt), 0); - SetCC(CC_EQ); + FixupBranch zeroSkip = B(); + SetJumpTarget(skipper); // TODO: Is this correct? MOV(gpr.R(MIPS_REG_LO), 0); MOV(gpr.R(MIPS_REG_HI), 0); - SetCC(CC_AL); + SetJumpTarget(zeroSkip); } } break; diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 5887ae8211..4577a46048 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -287,8 +287,8 @@ void Jit::BranchFPFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely) if (!likely && delaySlotIsNice) CompileDelaySlot(DELAYSLOT_NICE); - LDR(R0, CTXREG, offsetof(MIPSState, fpcond)); - TST(R0, Operand2(1, TYPE_IMM)); + gpr.MapReg(MIPS_REG_FPCOND); + TST(gpr.R(MIPS_REG_FPCOND), Operand2(1, TYPE_IMM)); ArmGen::FixupBranch ptr; if (!likely) @@ -340,7 +340,7 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely) u32 targetAddr = js.compilerPC + offset + 4; MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4); - + // Sometimes there's a VFPU branch in a delay slot (Disgaea 2: Dark Hero Days, Zettai Hero Project, La Pucelle) // The behavior is undefined - the CPU may take the second branch even if the first one passes. // However, it does consistently try each branch, which these games seem to expect. @@ -354,8 +354,8 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely) int imm3 = (op >> 18) & 7; - LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC])); - TST(R0, Operand2(1 << imm3, TYPE_IMM)); + gpr.MapReg(MIPS_REG_VFPUCC); + TST(gpr.R(MIPS_REG_VFPUCC), Operand2(1 << imm3, TYPE_IMM)); ArmGen::FixupBranch ptr; js.inDelaySlot = true; @@ -461,23 +461,28 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } MIPSGPReg rs = _RS; MIPSGPReg rd = _RD; + bool andLink = (op & 0x3f) == 9; MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4); bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs); + if (andLink && rs == rd) + delaySlotIsNice = false; CONDITIONAL_NICE_DELAYSLOT; ARMReg destReg = R8; if (IsSyscall(delaySlotOp)) { - _dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported."); - gpr.MapReg(rs); MovToPC(gpr.R(rs)); // For syscall to be able to return. + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_FLUSH); return; // Syscall wrote exit code. } else if (delaySlotIsNice) { + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { // According to the MIPS ABI, there are some regs we don't need to preserve. // Let's discard them so we don't need to write them back. // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash @@ -492,9 +497,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) { // Account for the increment in the loop. js.compilerPC = gpr.GetImm(rs) - 4; - if ((op & 0x3f) == 9) { - gpr.SetImm(rd, js.compilerPC + 8); - } // In case the delay slot was a break or something. js.compiling = true; return; @@ -507,6 +509,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op) // Delay slot - this case is very rare, might be able to free up R8. gpr.MapReg(rs); MOV(R8, gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); FlushAll(); } @@ -516,8 +520,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) case 8: //jr break; case 9: //jalr - gpr.SetRegImm(R0, js.compilerPC + 8); - STR(R0, CTXREG, (int)rd * 4); break; default: _dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled"); diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index 388ddc08e9..19f11f2a37 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -117,7 +117,7 @@ void Jit::Comp_FPULS(MIPSOpcode op) SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -161,7 +161,7 @@ void Jit::Comp_FPULS(MIPSOpcode op) SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip2; @@ -192,13 +192,13 @@ void Jit::Comp_FPUComp(MIPSOpcode op) { int opc = op & 0xF; if (opc >= 8) opc -= 8; // alias if (opc == 0) { // f, sf (signalling false) - MOVI2R(R0, 0); - STR(R0, CTXREG, offsetof(MIPSState, fpcond)); + gpr.SetImm(MIPS_REG_FPCOND, 0); return; } int fs = _FS; int ft = _FT; + gpr.MapReg(MIPS_REG_FPCOND, MAP_DIRTY | MAP_NOINIT); fpr.MapInIn(fs, ft); VCMP(fpr.R(fs), fpr.R(ft)); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). @@ -206,62 +206,58 @@ void Jit::Comp_FPUComp(MIPSOpcode op) { { case 1: // un, ngle (unordered) SetCC(CC_VS); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_VC); break; case 2: // eq, seq (equal, ordered) SetCC(CC_EQ); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_NEQ); break; case 3: // ueq, ngl (equal, unordered) SetCC(CC_EQ); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_NEQ); - MOVI2R(R0, 0); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 0); SetCC(CC_VS); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_AL); - STR(R0, CTXREG, offsetof(MIPSState, fpcond)); return; case 4: // olt, lt (less than, ordered) SetCC(CC_LO); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_HS); break; case 5: // ult, nge (less than, unordered) SetCC(CC_LT); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_GE); break; case 6: // ole, le (less equal, ordered) SetCC(CC_LS); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_HI); break; case 7: // ule, ngt (less equal, unordered) SetCC(CC_LE); - MOVI2R(R0, 1); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 1); SetCC(CC_GT); break; default: Comp_Generic(op); return; } - MOVI2R(R0, 0); + MOVI2R(gpr.R(MIPS_REG_FPCOND), 0); SetCC(CC_AL); - STR(R0, CTXREG, offsetof(MIPSState, fpcond)); } -void Jit::Comp_FPU2op(MIPSOpcode op) -{ +void Jit::Comp_FPU2op(MIPSOpcode op) { CONDITIONAL_DISABLE; int fs = _FS; int fd = _FD; - switch (op & 0x3f) - { + switch (op & 0x3f) { case 4: //F(fd) = sqrtf(F(fs)); break; //sqrt fpr.MapDirtyIn(fd, fs); VSQRT(fpr.R(fd), fpr.R(fs)); @@ -343,23 +339,21 @@ void Jit::Comp_mxc1(MIPSOpcode op) return; case 2: //cfc1 - if (fs == 31) - { - gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT); - LDR(R0, CTXREG, offsetof(MIPSState, fpcond)); + if (fs == 31) { + gpr.MapDirtyIn(rt, MIPS_REG_FPCOND); LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31)); - if (cpu_info.bArmV7) { - BFI(gpr.R(rt), R0, 23, 1); - } else { - AND(R0, R0, Operand2(1)); // Just in case - ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), R1); // R1 won't be used, this turns into a simple BIC. - ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23)); - } - } - else if (fs == 0) - { - gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT); - LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr0)); +#ifdef HAVE_ARMV7 + BFI(gpr.R(rt), gpr.R(MIPS_REG_FPCOND), 23, 1); +#else + AND(R0, gpr.R(MIPS_REG_FPCOND), Operand2(1)); // Just in case + ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), R1); // R1 won't be used, this turns into a simple BIC. + ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23)); +#endif + } else if (fs == 0) { + gpr.SetImm(rt, MIPSState::FCR0_VALUE); + } else { + // Unsupported regs are always 0. + gpr.SetImm(rt, 0); } return; @@ -372,7 +366,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) case 6: //ctc1 if (fs == 31) { - gpr.MapReg(rt, 0); + gpr.MapDirtyIn(MIPS_REG_FPCOND, rt); // Hardware rounding method. // Left here in case it is faster than conditional method. /* @@ -391,14 +385,14 @@ void Jit::Comp_mxc1(MIPSOpcode op) VMSR(R1); */ // Update MIPS state + // TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg? STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31)); - if (cpu_info.bArmV7) { - UBFX(R0, gpr.R(rt), 23, 1); - } else { - MOV(R0, Operand2(gpr.R(rt), ST_LSR, 23)); - AND(R0, R0, Operand2(1)); - } - STR(R0, CTXREG, offsetof(MIPSState, fpcond)); +#ifdef HAVE_ARMV7 + UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1); +#else + MOV(R0, Operand2(gpr.R(rt), ST_LSR, 23)); + AND(gpr.R(MIPS_REG_FPCOND), R0, Operand2(1)); +#endif } return; } diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index 1786c45c06..6a10aa31ca 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -162,31 +162,31 @@ namespace MIPSComp switch (o) { case 34: // lwl - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); ANDI2R(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift, R1); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift)); break; case 38: // lwr - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); ANDI2R(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift), R1); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift)); break; case 42: // swl - LDR(R1, R11, R0); + LDR(R1, MEMBASEREG, R0); // Don't worry, can't use temporary. ANDI2R(R1, R1, 0xffffff00 << shift, R0); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSR, 24 - shift)); - STR(R1, R11, R0); + STR(R1, MEMBASEREG, R0); break; case 46: // swr - LDR(R1, R11, R0); + LDR(R1, MEMBASEREG, R0); // Don't worry, can't use temporary. ANDI2R(R1, R1, 0x00ffffff >> (24 - shift), R0); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSL, shift)); - STR(R1, R11, R0); + STR(R1, MEMBASEREG, R0); break; } return; @@ -223,7 +223,7 @@ namespace MIPSComp switch (o) { case 34: // lwl MOVI2R(R10, 0x00ffffff); - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSR, R1)); RSB(R1, R1, 24); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, R1)); @@ -231,7 +231,7 @@ namespace MIPSComp case 38: // lwr MOVI2R(R10, 0xffffff00); - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); LSR(R0, R0, R1); RSB(R1, R1, 24); AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSL, R1)); @@ -240,21 +240,21 @@ namespace MIPSComp case 42: // swl MOVI2R(R10, 0xffffff00); - LDR(R9, R11, R0); + LDR(R9, MEMBASEREG, R0); AND(R9, R9, Operand2(R10, ST_LSL, R1)); RSB(R1, R1, 24); ORR(R9, R9, Operand2(gpr.R(rt), ST_LSR, R1)); - STR(R9, R11, R0); + STR(R9, MEMBASEREG, R0); break; case 46: // swr MOVI2R(R10, 0x00ffffff); - LDR(R9, R11, R0); + LDR(R9, MEMBASEREG, R0); RSB(R1, R1, 24); AND(R9, R9, Operand2(R10, ST_LSR, R1)); RSB(R1, R1, 24); ORR(R9, R9, Operand2(gpr.R(rt), ST_LSL, R1)); - STR(R9, R11, R0); + STR(R9, MEMBASEREG, R0); break; } @@ -353,15 +353,15 @@ namespace MIPSComp switch (o) { // Load - case 35: LDR (gpr.R(rt), R11, addrReg); break; - case 37: LDRH (gpr.R(rt), R11, addrReg); break; - case 33: LDRSH(gpr.R(rt), R11, addrReg); break; - case 36: LDRB (gpr.R(rt), R11, addrReg); break; - case 32: LDRSB(gpr.R(rt), R11, addrReg); break; + case 35: LDR (gpr.R(rt), MEMBASEREG, addrReg); break; + case 37: LDRH (gpr.R(rt), MEMBASEREG, addrReg); break; + case 33: LDRSH(gpr.R(rt), MEMBASEREG, addrReg); break; + case 36: LDRB (gpr.R(rt), MEMBASEREG, addrReg); break; + case 32: LDRSB(gpr.R(rt), MEMBASEREG, addrReg); break; // Store - case 43: STR (gpr.R(rt), R11, addrReg); break; - case 41: STRH (gpr.R(rt), R11, addrReg); break; - case 40: STRB (gpr.R(rt), R11, addrReg); break; + case 43: STR (gpr.R(rt), MEMBASEREG, addrReg); break; + case 41: STRH (gpr.R(rt), MEMBASEREG, addrReg); break; + case 40: STRB (gpr.R(rt), MEMBASEREG, addrReg); break; } if (doCheck) { if (load) { @@ -385,8 +385,6 @@ namespace MIPSComp } void Jit::Comp_Cache(MIPSOpcode op) { - CONDITIONAL_DISABLE; - // TODO: Could use this as a hint, and technically required to handle icache, etc. - // But right now Int_Cache does nothing, so let's not even call it. + DISABLE; } } diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index bb244231b0..95161ea417 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -32,15 +32,14 @@ // Cool NEON references: // http://www.delmarnorth.com/microwave/requirements/neon-test-tutorial.pdf -const bool disablePrefixes = false; - // All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. // Currently known non working ones should have DISABLE. -// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocks(); Comp_Generic(op); return; } +// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; } + #define CONDITIONAL_DISABLE ; #define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; } - +#define NEON_IF_AVAILABLE(func) { if (jo.useNEONVFPU) { func(op); return; } } #define _RS MIPS_GET_RS(op) #define _RT MIPS_GET_RT(op) #define _RD MIPS_GET_RD(op) @@ -202,13 +201,6 @@ namespace MIPSComp SetCC(CC_GT); VMOV(fpr.V(vregs[i]), S1); SetCC(CC_AL); - - /* - VABS(S1, fpr.V(vregs[i])); // S1 = fabs(x) - VSUB(fpr.V(vregs[i]), fpr.V(vregs[i]), S0); // S2 = fabs(x-0.5f) {VABD} - VABS(fpr.V(vregs[i]), fpr.V(vregs[i])); - VSUB(fpr.V(vregs[i]), S1, fpr.V(vregs[i])); // v[i] = S1 - S2 + 0.5f - VADD(fpr.V(vregs[i]), fpr.V(vregs[i]), S0);*/ } else if (sat == 3) { fpr.MapRegV(vregs[i], MAP_DIRTY); @@ -224,24 +216,15 @@ namespace MIPSComp SetCC(CC_GT); VMOV(fpr.V(vregs[i]), S1); SetCC(CC_AL); - - // clamped = fabs(x) - fabs(x-1.0f); // [-1, 1] - /* - fpr.MapRegV(vregs[i], MAP_DIRTY); - MOVI2F(S0, 1.0f, R0); - VABS(S1, fpr.V(vregs[i])); // S1 = fabs(x) - VSUB(fpr.V(vregs[i]), fpr.V(vregs[i]), S0); // S2 = fabs(x-1.0f) {VABD} - VABS(fpr.V(vregs[i]), fpr.V(vregs[i])); - VSUB(fpr.V(vregs[i]), S1, fpr.V(vregs[i])); // v[i] = S1 - S2 - */ } } } void Jit::Comp_SV(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_SV); CONDITIONAL_DISABLE; - s32 imm = (signed short)(op&0xFFFC); + s32 offset = (signed short)(op & 0xFFFC); int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5); MIPSGPReg rs = _RS; @@ -250,20 +233,27 @@ namespace MIPSComp { case 50: //lv.s // VI(vt) = Memory::Read_U32(addr); { + if (!gpr.IsImm(rs) && jo.cachePointers && g_Config.bFastMemory && (offset & 3) == 0 && offset < 0x400 && offset > -0x400) { + gpr.MapRegAsPointer(rs); + fpr.MapRegV(vt, MAP_NOINIT | MAP_DIRTY); + VLDR(fpr.V(vt), gpr.RPtr(rs), offset); + break; + } + // CC might be set by slow path below, so load regs first. fpr.MapRegV(vt, MAP_DIRTY | MAP_NOINIT); if (gpr.IsImm(rs)) { - u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; + u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF; gpr.SetRegImm(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { - SetR0ToEffectiveAddress(rs, imm); + SetR0ToEffectiveAddress(rs, offset); } else { - SetCCAndR0ForSafeAddress(rs, imm, R1); + SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -288,20 +278,27 @@ namespace MIPSComp case 58: //sv.s // Memory::Write_U32(VI(vt), addr); { + if (!gpr.IsImm(rs) && jo.cachePointers && g_Config.bFastMemory && (offset & 3) == 0 && offset < 0x400 && offset > -0x400) { + gpr.MapRegAsPointer(rs); + fpr.MapRegV(vt, 0); + VSTR(fpr.V(vt), gpr.RPtr(rs), offset); + break; + } + // CC might be set by slow path below, so load regs first. fpr.MapRegV(vt); if (gpr.IsImm(rs)) { - u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; + u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF; gpr.SetRegImm(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { - SetR0ToEffectiveAddress(rs, imm); + SetR0ToEffectiveAddress(rs, offset); } else { - SetCCAndR0ForSafeAddress(rs, imm, R1); + SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -331,6 +328,7 @@ namespace MIPSComp void Jit::Comp_SVQ(MIPSOpcode op) { CONDITIONAL_DISABLE; + NEON_IF_AVAILABLE(CompNEON_SVQ); int imm = (signed short)(op&0xFFFC); int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5); @@ -357,7 +355,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ @@ -406,7 +404,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ @@ -442,10 +440,10 @@ namespace MIPSComp void Jit::Comp_VVectorInit(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VVectorInit); CONDITIONAL_DISABLE; - // WARNING: No prefix support! - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -478,9 +476,9 @@ namespace MIPSComp } void Jit::Comp_VIdt(MIPSOpcode op) { - CONDITIONAL_DISABLE - - if (js.HasUnknownPrefix() || disablePrefixes) { + NEON_IF_AVAILABLE(CompNEON_VIdt); + CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) { DISABLE; } @@ -516,9 +514,9 @@ namespace MIPSComp void Jit::Comp_VMatrixInit(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VMatrixInit); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { // Don't think matrix init ops care about prefixes. // DISABLE; } @@ -564,10 +562,9 @@ namespace MIPSComp } void Jit::Comp_VHdp(MIPSOpcode op) { - // DISABLE; - + NEON_IF_AVAILABLE(CompNEON_VHdp); CONDITIONAL_DISABLE; - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -606,8 +603,9 @@ namespace MIPSComp } void Jit::Comp_VDot(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VDot); CONDITIONAL_DISABLE; - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -642,9 +640,9 @@ namespace MIPSComp } void Jit::Comp_VecDo3(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VecDo3); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -757,9 +755,9 @@ namespace MIPSComp } void Jit::Comp_VV2Op(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VV2Op); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -784,6 +782,19 @@ namespace MIPSComp } } + // Get some extra temps, used by vasin only. + ARMReg t2 = INVALID_REG, t3 = INVALID_REG, t4 = INVALID_REG; + if (((op >> 16) & 0x1f) == 23) { + // Only get here on vasin. + int t[3] = { fpr.GetTempV(), fpr.GetTempV(), fpr.GetTempV() }; + fpr.MapRegV(t[0], MAP_NOINIT); + fpr.MapRegV(t[1], MAP_NOINIT); + fpr.MapRegV(t[2], MAP_NOINIT); + t2 = fpr.V(t[0]); + t3 = fpr.V(t[1]); + t4 = fpr.V(t[2]); + } + // Warning: sregs[i] and tempxregs[i] may be the same reg. // Helps for vmov, hurts for vrcp, etc. for (int i = 0; i < n; ++i) { @@ -851,7 +862,34 @@ namespace MIPSComp VABS(fpr.V(tempregs[i]), fpr.V(tempregs[i])); break; case 23: // d[i] = asinf(s[i] * (float)M_2_PI); break; //vasin - DISABLE; + // Seems to work well enough but can disable if it becomes a problem. + // Should be easy enough to translate to NEON. There we can load all the constants + // in one go of course. + fpr.MapDirtyInV(tempregs[i], sregs[i]); + MOVI2F(S0, 0.0f, R0); + VCMP(fpr.V(sregs[i]), S0); // flags = sign(sregs[i]) + VMRS_APSR(); + MOVI2F(S0, 1.0f, R0); + VABS(t4, fpr.V(sregs[i])); // t4 = |sregs[i]| + VSUB(t3, S0, t4); + VSQRT(t3, t3); // t3 = sqrt(1 - |sregs[i]|) + MOVI2F(S1, -0.0187293f, R0); + MOVI2F(t2, 0.0742610f, R0); + VMLA(t2, t4, S1); + MOVI2F(S1, -0.2121144f, R0); + VMLA(S1, t4, t2); + MOVI2F(t2, 1.5707288f, R0); + VMLA(t2, t4, S1); + MOVI2F(fpr.V(tempregs[i]), M_PI / 2, R0); + VMLS(fpr.V(tempregs[i]), t2, t3); // tr[i] = M_PI / 2 - t2 * t3 + { + FixupBranch br = B_CC(CC_GE); + VNEG(fpr.V(tempregs[i]), fpr.V(tempregs[i])); + SetJumpTarget(br); + } + // Correction factor for PSP range. Could be baked into the calculation above? + MOVI2F(S1, 1.0f / (M_PI / 2), R0); + VMUL(fpr.V(tempregs[i]), fpr.V(tempregs[i]), S1); break; case 24: // d[i] = -1.0f / s[i]; break; // vnrcp fpr.MapDirtyInV(tempregs[i], sregs[i]); @@ -883,10 +921,11 @@ namespace MIPSComp } void Jit::Comp_Vi2f(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vi2f); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) + if (js.HasUnknownPrefix()) { DISABLE; + } VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); @@ -929,15 +968,75 @@ namespace MIPSComp } void Jit::Comp_Vh2f(MIPSOpcode op) { - DISABLE; + NEON_IF_AVAILABLE(CompNEON_Vh2f); + CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) { + DISABLE; + } + + if (!cpu_info.bNEON) { + DISABLE; + } + + // This multi-VCVT.F32.F16 is only available in the VFPv4 extension. + // The VFPv3 one is VCVTB, VCVTT which we don't yet have support for. + if (!(cpu_info.bHalf && cpu_info.bVFPv4)) { + // No hardware support for half-to-float, fallback to interpreter + // TODO: Translate the fast SSE solution to standard integer/VFP stuff + // for the weaker CPUs. + DISABLE; + } + + u8 sregs[4], dregs[4]; + VectorSize sz = GetVecSize(op); + VectorSize outSz; + + switch (sz) { + case V_Single: + outSz = V_Pair; + break; + case V_Pair: + outSz = V_Quad; + break; + default: + DISABLE; + } + + int n = GetNumVectorElements(sz); + int nOut = n * 2; + GetVectorRegsPrefixS(sregs, sz, _VS); + GetVectorRegsPrefixD(dregs, outSz, _VD); + + static const ARMReg tmp[4] = { S0, S1, S2, S3 }; + + for (int i = 0; i < n; i++) { + fpr.MapRegV(sregs[i], sz); + VMOV(tmp[i], fpr.V(sregs[i])); + } + + // This always converts four 32-bit floats in Q0 to four 16-bit floats + // in D0. If we are dealing with a pair here, we just ignore the upper two outputs. + // There are also a couple of other instructions that do it one at a time but doesn't + // seem worth the trouble. + VCVTF32F16(Q0, D0); + + for (int i = 0; i < nOut; i++) { + fpr.MapRegV(dregs[i], MAP_DIRTY | MAP_NOINIT); + VMOV(fpr.V(dregs[i]), tmp[i]); + } + + ApplyPrefixD(dregs, sz); + fpr.ReleaseSpillLocksAndDiscardTemps(); } void Jit::Comp_Vf2i(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vf2i); CONDITIONAL_DISABLE; - DISABLE; - if (js.HasUnknownPrefix()) + if (js.HasUnknownPrefix()) { DISABLE; + } + DISABLE; VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); @@ -1000,14 +1099,13 @@ namespace MIPSComp fpr.ReleaseSpillLocksAndDiscardTemps(); } - void Jit::Comp_Mftv(MIPSOpcode op) - { + void Jit::Comp_Mftv(MIPSOpcode op) { CONDITIONAL_DISABLE; + NEON_IF_AVAILABLE(CompNEON_Mftv); int imm = op & 0xFF; MIPSGPReg rt = _RT; - switch ((op >> 21) & 0x1f) - { + switch ((op >> 21) & 0x1f) { case 3: //mfv / mfvc // rt = 0, imm = 255 appears to be used as a CPU interlock by some games. if (rt != 0) { @@ -1018,8 +1116,13 @@ namespace MIPSComp } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc // In case we have a saved prefix. FlushPrefixV(); - gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); - LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128)); + if (imm - 128 == VFPU_CTRL_CC) { + gpr.MapDirtyIn(rt, MIPS_REG_VFPUCC); + MOV(gpr.R(rt), gpr.R(MIPS_REG_VFPUCC)); + } else { + gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); + LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128)); + } } else { //ERROR - maybe need to make this value too an "interlock" value? ERROR_LOG(CPU, "mfv - invalid register %i", imm); @@ -1033,8 +1136,13 @@ namespace MIPSComp fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); VMOV(fpr.V(imm), gpr.R(rt)); } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc //currentMIPS->vfpuCtrl[imm - 128] = R(rt); - gpr.MapReg(rt); - STR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128)); + if (imm - 128 == VFPU_CTRL_CC) { + gpr.MapDirtyIn(MIPS_REG_VFPUCC, rt); + MOV(gpr.R(MIPS_REG_VFPUCC), gpr.R(rt)); + } else { + gpr.MapReg(rt); + STR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128)); + } //gpr.BindToRegister(rt, true, false); //MOV(32, M(¤tMIPS->vfpuCtrl[imm - 128]), gpr.R(rt)); @@ -1061,6 +1169,7 @@ namespace MIPSComp } void Jit::Comp_Vmtvc(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vmtvc); CONDITIONAL_DISABLE; int vs = _VS; @@ -1082,16 +1191,13 @@ namespace MIPSComp } void Jit::Comp_Vmmov(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vmmov); CONDITIONAL_DISABLE; - // TODO: This probably ignores prefixes? - //if (js.MayHavePrefix()) { - // DISABLE; - //} - + // This probably ignores prefixes for all sane intents and purposes. if (_VS == _VD) { - // A lot of these in Wipeout... Just drop the instruction entirely. - return; + // A lot of these no-op matrix moves in Wipeout... Just drop the instruction entirely. + return; } MatrixSize sz = GetMtxSize(op); @@ -1123,9 +1229,9 @@ namespace MIPSComp } void Jit::Comp_VScl(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VScl); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -1173,11 +1279,12 @@ namespace MIPSComp void Jit::Comp_Vmmul(MIPSOpcode op) { CONDITIONAL_DISABLE; - - // TODO: This probably ignores prefixes? - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } + NEON_IF_AVAILABLE(CompNEON_Vmmul); + + // TODO: This probably ignores prefixes? MatrixSize sz = GetMtxSize(op); int n = GetMatrixSide(sz); @@ -1214,17 +1321,19 @@ namespace MIPSComp } void Jit::Comp_Vmscl(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vmscl); DISABLE; } void Jit::Comp_Vtfm(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vtfm); CONDITIONAL_DISABLE; - - // TODO: This probably ignores prefixes? Or maybe uses D? - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } + // TODO: This probably ignores prefixes? Or maybe uses D? + VectorSize sz = GetVecSize(op); MatrixSize msz = GetMtxSize(op); int n = GetNumVectorElements(sz); @@ -1278,24 +1387,30 @@ namespace MIPSComp } void Jit::Comp_VCrs(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VCrs); DISABLE; } void Jit::Comp_VDet(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_VDet); DISABLE; } void Jit::Comp_Vi2x(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vi2x); DISABLE; } void Jit::Comp_Vx2i(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vx2i); DISABLE; } void Jit::Comp_VCrossQuat(MIPSOpcode op) { - // This op does not support prefixes. - if (js.HasUnknownPrefix() || disablePrefixes) + NEON_IF_AVAILABLE(CompNEON_VCrossQuat); + // This op does not support prefixes anyway. + CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) DISABLE; VectorSize sz = GetVecSize(op); @@ -1340,9 +1455,9 @@ namespace MIPSComp } void Jit::Comp_Vcmp(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vcmp); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) + if (js.HasUnknownPrefix()) DISABLE; VectorSize sz = GetVecSize(op); @@ -1355,12 +1470,20 @@ namespace MIPSComp GetVectorRegsPrefixT(tregs, sz, _VT); // Some, we just fall back to the interpreter. + // ES is just really equivalent to (value & 0x7F800000) == 0x7F800000. + switch (cond) { case VC_EI: // c = my_isinf(s[i]); break; - case VC_ES: // c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection case VC_NI: // c = !my_isinf(s[i]); break; - case VC_NS: // c = !my_isnan(s[i]) && !my_isinf(s[i]); break; DISABLE; + case VC_ES: // c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection + case VC_NS: // c = !my_isnan(s[i]) && !my_isinf(s[i]); break; + case VC_EN: // c = my_isnan(s[i]); break; + case VC_NN: // c = !my_isnan(s[i]); break; + if (_VS != _VT) + DISABLE; + break; + case VC_EZ: case VC_NZ: MOVI2F(S0, 0.0f, R0); @@ -1381,13 +1504,37 @@ namespace MIPSComp break; case VC_TR: // c = 1 - ORR(R0, R0, 1 << n); + if (i == 0) { + if (n == 1) { + MOVI2R(R0, 0x31); + } else { + MOVI2R(R0, 1 << i); + } + } else { + ORR(R0, R0, 1 << i); + } + break; + + case VC_ES: // c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection + case VC_NS: // c = !(my_isnan(s[i]) || my_isinf(s[i])); break; + // For these, we use the integer ALU as there is no support on ARM for testing for INF. + // Testing for nan or inf is the same as testing for &= 0x7F800000 == 0x7F800000. + // We need an extra temporary register so we store away R0. + STR(R0, CTXREG, offsetof(MIPSState, temp)); + fpr.MapRegV(sregs[i], 0); + MOVI2R(R0, 0x7F800000); + VMOV(R1, fpr.V(sregs[i])); + AND(R1, R1, R0); + CMP(R1, R0); // (R1 & 0x7F800000) == 0x7F800000 + flag = cond == VC_ES ? CC_EQ : CC_NEQ; + LDR(R0, CTXREG, offsetof(MIPSState, temp)); break; case VC_EN: // c = my_isnan(s[i]); break; // Tekken 6 // Should we involve T? Where I found this used, it compared a register with itself so should be fine. fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_VS; // overflow = unordered : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/Chdhcfbc.html break; @@ -1395,54 +1542,63 @@ namespace MIPSComp // Should we involve T? Where I found this used, it compared a register with itself so should be fine. fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_VC; // !overflow = !unordered : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/Chdhcfbc.html break; case VC_EQ: // c = s[i] == t[i] fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_EQ; break; case VC_LT: // c = s[i] < t[i] fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_LT; break; case VC_LE: // c = s[i] <= t[i]; fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_LE; break; case VC_NE: // c = s[i] != t[i] fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_NEQ; break; case VC_GE: // c = s[i] >= t[i] fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_GE; break; case VC_GT: // c = s[i] > t[i] fpr.MapInInV(sregs[i], tregs[i]); VCMP(fpr.V(sregs[i]), fpr.V(tregs[i])); + VMRS_APSR(); flag = CC_GT; break; case VC_EZ: // c = s[i] == 0.0f || s[i] == -0.0f fpr.MapRegV(sregs[i]); VCMP(fpr.V(sregs[i]), S0); + VMRS_APSR(); flag = CC_EQ; break; case VC_NZ: // c = s[i] != 0 fpr.MapRegV(sregs[i]); VCMP(fpr.V(sregs[i]), S0); + VMRS_APSR(); flag = CC_NEQ; break; @@ -1450,13 +1606,12 @@ namespace MIPSComp DISABLE; } if (flag != CC_AL) { - VMRS_APSR(); SetCC(flag); if (i == 0) { if (n == 1) { MOVI2R(R0, 0x31); } else { - MOVI2R(R0, 1 << i); + MOVI2R(R0, 1); // 1 << i, but i == 0 } } else { ORR(R0, R0, 1 << i); @@ -1474,26 +1629,26 @@ namespace MIPSComp SetCC(CC_EQ); ORR(R0, R0, 1 << 5); SetCC(CC_AL); - + CMP(R0, 0); SetCC(CC_NEQ); ORR(R0, R0, 1 << 4); SetCC(CC_AL); } - LDR(R1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC])); - BIC(R1, R1, affected_bits); - ORR(R1, R1, R0); - STR(R1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC])); + gpr.MapReg(MIPS_REG_VFPUCC, MAP_DIRTY); + BIC(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), affected_bits); + ORR(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), R0); fpr.ReleaseSpillLocksAndDiscardTemps(); } void Jit::Comp_Vcmov(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vcmov); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) + if (js.HasUnknownPrefix()) { DISABLE; + } VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); @@ -1515,8 +1670,8 @@ namespace MIPSComp // Test one bit of CC. This bit decides whether none or all subregisters are copied. fpr.MapRegsAndSpillLockV(dregs, sz, MAP_DIRTY); fpr.MapRegsAndSpillLockV(sregs, sz, 0); - LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC])); - TST(R0, 1 << imm3); + gpr.MapReg(MIPS_REG_VFPUCC); + TST(gpr.R(MIPS_REG_VFPUCC), 1 << imm3); SetCC(tf ? CC_EQ : CC_NEQ); for (int i = 0; i < n; i++) { VMOV(fpr.V(dregs[i]), fpr.V(sregs[i])); @@ -1526,18 +1681,21 @@ namespace MIPSComp // Look at the bottom four bits of CC to individually decide if the subregisters should be copied. fpr.MapRegsAndSpillLockV(dregs, sz, MAP_DIRTY); fpr.MapRegsAndSpillLockV(sregs, sz, 0); - LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC])); + gpr.MapReg(MIPS_REG_VFPUCC); for (int i = 0; i < n; i++) { - TST(R0, 1 << i); + TST(gpr.R(MIPS_REG_VFPUCC), 1 << i); SetCC(tf ? CC_EQ : CC_NEQ); VMOV(fpr.V(dregs[i]), fpr.V(sregs[i])); SetCC(CC_AL); } } + + ApplyPrefixD(dregs, sz); fpr.ReleaseSpillLocksAndDiscardTemps(); } void Jit::Comp_Viim(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Viim); CONDITIONAL_DISABLE; u8 dreg; @@ -1552,9 +1710,9 @@ namespace MIPSComp } void Jit::Comp_Vfim(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vfim); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -1572,9 +1730,9 @@ namespace MIPSComp } void Jit::Comp_Vcst(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vcst); CONDITIONAL_DISABLE; - - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -1619,13 +1777,14 @@ namespace MIPSComp sincostemp[1] = cosf(angle); } - // Very heavily used by FF:CC + // Very heavily used by FF:CC. Should be replaced by a fast approximation instead of + // calling the math library. + // Apparently this may not work on hardfp. I don't think we have any platforms using this though. void Jit::Comp_VRot(MIPSOpcode op) { - // Apparently this may not work on hardfp. I don't think we have any platforms using this though. + NEON_IF_AVAILABLE(CompNEON_VRot); + // VRot probably doesn't accept prefixes anyway. CONDITIONAL_DISABLE; - - // This op doesn't support prefixes anyway.. - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -1683,8 +1842,10 @@ namespace MIPSComp } void Jit::Comp_Vhoriz(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vhoriz); DISABLE; + // Do any games use these a noticable amount? switch ((op >> 16) & 31) { case 6: // vfad break; @@ -1694,8 +1855,9 @@ namespace MIPSComp } void Jit::Comp_Vsgn(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vsgn); CONDITIONAL_DISABLE; - if (js.HasUnknownPrefix() || disablePrefixes) { + if (js.HasUnknownPrefix()) { DISABLE; } @@ -1722,12 +1884,13 @@ namespace MIPSComp // care of NaNs like the interpreter (ignores them and just operates on the bits). MOVI2F(S0, 0.0f, R0); VCMP(fpr.V(sregs[i]), S0); - VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). VMOV(R0, fpr.V(sregs[i])); + VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). + SetCC(CC_NEQ); AND(R0, R0, AssumeMakeOperand2(0x80000000)); ORR(R0, R0, AssumeMakeOperand2(0x3F800000)); SetCC(CC_EQ); - MOV(R1, AssumeMakeOperand2(0x0)); + MOV(R0, AssumeMakeOperand2(0x0)); SetCC(CC_AL); VMOV(fpr.V(tempregs[i]), R0); } @@ -1743,4 +1906,51 @@ namespace MIPSComp fpr.ReleaseSpillLocksAndDiscardTemps(); } + + void Jit::Comp_Vocp(MIPSOpcode op) { + NEON_IF_AVAILABLE(CompNEON_Vocp); + CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) { + DISABLE; + } + + VectorSize sz = GetVecSize(op); + int n = GetNumVectorElements(sz); + + u8 sregs[4], dregs[4]; + // Actually, not sure that this instruction accepts an S prefix. We don't apply it in the + // interpreter. But whatever. + GetVectorRegsPrefixS(sregs, sz, _VS); + GetVectorRegsPrefixD(dregs, sz, _VD); + + MIPSReg tempregs[4]; + for (int i = 0; i < n; ++i) { + if (!IsOverlapSafe(dregs[i], i, n, sregs)) { + tempregs[i] = fpr.GetTempV(); + } else { + tempregs[i] = dregs[i]; + } + } + + MOVI2F(S0, 1.0f, R0); + for (int i = 0; i < n; ++i) { + fpr.MapDirtyInV(tempregs[i], sregs[i]); + // Let's do it integer registers for now. NEON later. + // There's gotta be a shorter way, can't find one though that takes + // care of NaNs like the interpreter (ignores them and just operates on the bits). + VSUB(fpr.V(tempregs[i]), S0, fpr.V(sregs[i])); + } + + for (int i = 0; i < n; ++i) { + if (dregs[i] != tempregs[i]) { + fpr.MapDirtyInV(dregs[i], tempregs[i]); + VMOV(fpr.V(dregs[i]), fpr.V(tempregs[i])); + } + } + + ApplyPrefixD(dregs, sz); + + fpr.ReleaseSpillLocksAndDiscardTemps(); + } + } diff --git a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp new file mode 100644 index 0000000000..4ec568a79d --- /dev/null +++ b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +// NEON VFPU +// This is where we will create an alternate implementation of the VFPU emulation +// that uses NEON Q registers to cache pairs/tris/quads, and so on. +// Will require major extensions to the reg cache and other things. + +#include +#include "math/math_util.h" + +#include "Common/CPUDetect.h" +#include "Core/MemMap.h" +#include "Core/MIPS/MIPS.h" +#include "Core/MIPS/MIPSAnalyst.h" +#include "Core/MIPS/MIPSCodeUtils.h" +#include "Core/Config.h" +#include "Core/Reporting.h" + +#include "Core/MIPS/ARM/ArmJit.h" +#include "Core/MIPS/ARM/ArmRegCache.h" + +// TODO: Somehow #ifdef away on ARMv5eabi, without breaking the linker. + +#define CONDITIONAL_DISABLE ; +#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; } + +namespace MIPSComp { + +void Jit::CompNEON_SV(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_SVQ(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VVectorInit(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VMatrixInit(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VDot(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VecDo3(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VV2Op(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Mftv(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vmtvc(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vmmov(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VScl(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vmmul(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vmscl(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vtfm(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VHdp(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VCrs(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VDet(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vi2x(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vx2i(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vf2i(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vi2f(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vh2f(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vcst(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vhoriz(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VRot(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VIdt(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vcmp(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vcmov(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Viim(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vfim(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_VCrossQuat(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vsgn(MIPSOpcode op) { + DISABLE; +} + +void Jit::CompNEON_Vocp(MIPSOpcode op) { + DISABLE; +} + +} +// namespace MIPSComp \ No newline at end of file diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index dd9eb7e015..35eeb95e22 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "base/logging.h" #include "Common/ChunkFile.h" #include "Core/Reporting.h" #include "Core/Core.h" @@ -44,21 +45,20 @@ void DisassembleArm(const u8 *data, int size) { int reg1 = (next & 0x0000F000) >> 12; if (reg0 == reg1) { sprintf(temp, "%08x MOV32? %s, %04x%04x", (u32)inst, ArmRegName(reg0), hi, low); - INFO_LOG(JIT, "A: %s", temp); + ILOG("A: %s", temp); i += 4; continue; } } ArmDis((u32)codePtr, inst, temp); - INFO_LOG(JIT, "A: %s", temp); + ILOG("A: %s", temp); } } namespace MIPSComp { -ArmJitOptions::ArmJitOptions() -{ +ArmJitOptions::ArmJitOptions() { enableBlocklink = true; downcountInRegister = true; useBackJump = false; @@ -70,6 +70,10 @@ ArmJitOptions::ArmJitOptions() continueBranches = false; continueJumps = false; continueMaxInstructions = 300; + + useNEONVFPU = false; // true + if (!cpu_info.bNEON) + useNEONVFPU = false; } Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &jo), fpr(mips), mips_(mips) @@ -145,12 +149,6 @@ void Jit::ClearCacheAt(u32 em_address, int length) blocks.InvalidateICache(em_address, length); } -void Jit::CompileAt(u32 addr) -{ - MIPSOpcode op = Memory::Read_Instruction(addr); - MIPSCompileOp(op); -} - void Jit::EatInstruction(MIPSOpcode op) { MIPSInfo info = MIPSGetInfo(op); if (info & DELAYSLOT) { @@ -184,6 +182,7 @@ void Jit::CompileDelaySlot(int flags) _MSR(true, false, R8); // Restore flags register } + void Jit::Compile(u32 em_address) { if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) { ClearCache(); @@ -277,7 +276,9 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b) js.compilerPC += 4; js.numInstructions++; - if (!cpu_info.bArmV7 && (GetCodePtr() - b->checkedEntry - partialFlushOffset) > 3200) +#ifndef HAVE_ARMV7 + // Disabled for now as it is crashing since Vertex Decoder JIT + if (false && (GetCodePtr() - b->checkedEntry - partialFlushOffset) > 3200) { // We need to prematurely flush as we are out of range FixupBranch skip = B_CC(CC_AL); @@ -285,6 +286,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b) SetJumpTarget(skip); partialFlushOffset = GetCodePtr() - b->checkedEntry; } +#endif // Safety check, in case we get a bunch of really large jit ops without a lot of branching. if (GetSpaceLeft() < 0x800) @@ -369,12 +371,12 @@ void Jit::MovToPC(ARMReg r) { void Jit::SaveDowncount() { if (jo.downcountInRegister) - STR(R7, CTXREG, offsetof(MIPSState, downcount)); + STR(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); } void Jit::RestoreDowncount() { if (jo.downcountInRegister) - LDR(R7, CTXREG, offsetof(MIPSState, downcount)); + LDR(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); } void Jit::WriteDownCount(int offset) @@ -383,12 +385,12 @@ void Jit::WriteDownCount(int offset) int theDowncount = js.downcountAmount + offset; Operand2 op2; if (TryMakeOperand2(theDowncount, op2)) { - SUBS(R7, R7, op2); + SUBS(DOWNCOUNTREG, DOWNCOUNTREG, op2); } else { // Should be fine to use R2 here, flushed the regcache anyway. // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway. gpr.SetRegImm(R2, theDowncount); - SUBS(R7, R7, R2); + SUBS(DOWNCOUNTREG, DOWNCOUNTREG, R2); } } else { int theDowncount = js.downcountAmount + offset; @@ -396,14 +398,13 @@ void Jit::WriteDownCount(int offset) Operand2 op2; if (TryMakeOperand2(theDowncount, op2)) { SUBS(R1, R1, op2); - STR(R1, CTXREG, offsetof(MIPSState, downcount)); } else { // Should be fine to use R2 here, flushed the regcache anyway. // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway. gpr.SetRegImm(R2, theDowncount); SUBS(R1, R1, R2); - STR(R1, CTXREG, offsetof(MIPSState, downcount)); } + STR(R1, CTXREG, offsetof(MIPSState, downcount)); } } diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index b5954e736e..994e4e1a59 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -36,6 +36,7 @@ struct ArmJitOptions { ArmJitOptions(); + bool useNEONVFPU; bool enableBlocklink; bool downcountInRegister; bool useBackJump; @@ -51,6 +52,7 @@ class Jit : public ArmGen::ARMXCodeBlock { public: Jit(MIPSState *mips); + void DoState(PointerWrap &p); static void DoDummyState(PointerWrap &p); @@ -64,8 +66,11 @@ public: void Compile(u32 em_address); // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); + bool IsInDispatch(const u8 *p) { + return IsInSpace(p); + } + void CompileDelaySlot(int flags); - void CompileAt(u32 addr); void EatInstruction(MIPSOpcode op); void Comp_RunBlock(MIPSOpcode op); @@ -132,6 +137,45 @@ public: void Comp_Vfim(MIPSOpcode op); void Comp_VCrossQuat(MIPSOpcode op); void Comp_Vsgn(MIPSOpcode op); + void Comp_Vocp(MIPSOpcode op); + + // Non-NEON: VPFX + + // NEON implementations of the VFPU ops. + void CompNEON_SV(MIPSOpcode op); + void CompNEON_SVQ(MIPSOpcode op); + void CompNEON_VVectorInit(MIPSOpcode op); + void CompNEON_VMatrixInit(MIPSOpcode op); + void CompNEON_VDot(MIPSOpcode op); + void CompNEON_VecDo3(MIPSOpcode op); + void CompNEON_VV2Op(MIPSOpcode op); + void CompNEON_Mftv(MIPSOpcode op); + void CompNEON_Vmtvc(MIPSOpcode op); + void CompNEON_Vmmov(MIPSOpcode op); + void CompNEON_VScl(MIPSOpcode op); + void CompNEON_Vmmul(MIPSOpcode op); + void CompNEON_Vmscl(MIPSOpcode op); + void CompNEON_Vtfm(MIPSOpcode op); + void CompNEON_VHdp(MIPSOpcode op); + void CompNEON_VCrs(MIPSOpcode op); + void CompNEON_VDet(MIPSOpcode op); + void CompNEON_Vi2x(MIPSOpcode op); + void CompNEON_Vx2i(MIPSOpcode op); + void CompNEON_Vf2i(MIPSOpcode op); + void CompNEON_Vi2f(MIPSOpcode op); + void CompNEON_Vh2f(MIPSOpcode op); + void CompNEON_Vcst(MIPSOpcode op); + void CompNEON_Vhoriz(MIPSOpcode op); + void CompNEON_VRot(MIPSOpcode op); + void CompNEON_VIdt(MIPSOpcode op); + void CompNEON_Vcmp(MIPSOpcode op); + void CompNEON_Vcmov(MIPSOpcode op); + void CompNEON_Viim(MIPSOpcode op); + void CompNEON_Vfim(MIPSOpcode op); + void CompNEON_VCrossQuat(MIPSOpcode op); + void CompNEON_Vsgn(MIPSOpcode op); + void CompNEON_Vocp(MIPSOpcode op); + JitBlockCache *GetBlockCache() { return &blocks; } diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index d05297009a..c8f4f86500 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -15,9 +15,11 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "ArmRegCache.h" -#include "ArmEmitter.h" -#include "ArmJit.h" +#include "Core/MIPS/ARM/ArmRegCache.h" +#include "Core/MIPS/ARM/ArmJit.h" +#include "Core/MIPS/MIPSAnalyst.h" +#include "Core/Reporting.h" +#include "Common/ArmEmitter.h" #if defined(MAEMO) #include "stddef.h" @@ -89,7 +91,7 @@ ARMReg ArmRegCache::MapRegAsPointer(MIPSGPReg mipsReg) { // read-only, non-dirt // Convert to a pointer by adding the base and clearing off the top bits. // If SP, we can probably avoid the top bit clear, let's play with that later. emit_->BIC(armReg, armReg, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - emit_->ADD(armReg, R11, armReg); + emit_->ADD(armReg, MEMBASEREG, armReg); ar[armReg].isDirty = false; ar[armReg].mipsReg = mipsReg; mr[mipsReg].loc = ML_ARMREG_AS_PTR; @@ -185,6 +187,38 @@ void ArmRegCache::MapRegTo(ARMReg reg, MIPSGPReg mipsReg, int mapFlags) { mr[mipsReg].reg = reg; } +ARMReg ArmRegCache::FindBestToSpill(bool unusedOnly) { + int allocCount; + const ARMReg *allocOrder = GetMIPSAllocationOrder(allocCount); + + static const int UNUSED_LOOKAHEAD_OPS = 3; + + for (int i = 0; i < allocCount; i++) { + ARMReg reg = allocOrder[i]; + if (ar[reg].mipsReg != MIPS_REG_INVALID && mr[ar[reg].mipsReg].spillLock) + continue; + + if (unusedOnly) { + bool unused = true; + for (int ahead = 1; ahead <= UNUSED_LOOKAHEAD_OPS; ++ahead) { + MIPSOpcode laterOp = Memory::Read_Instruction(compilerPC_ + ahead * sizeof(u32)); + // If read, it might need to be mapped again. If output, it might not need to be stored. + if (MIPSAnalyst::ReadsFromGPReg(laterOp, ar[reg].mipsReg) || MIPSAnalyst::GetOutGPReg(laterOp) == ar[reg].mipsReg) { + unused = false; + } + } + + if (!unused) { + continue; + } + } + + return reg; + } + + return INVALID_REG; +} + // TODO: Somewhat smarter spilling - currently simply spills the first available, should do // round robin or FIFO or something. ARMReg ArmRegCache::MapReg(MIPSGPReg mipsReg, int mapFlags) { @@ -194,7 +228,7 @@ ARMReg ArmRegCache::MapReg(MIPSGPReg mipsReg, int mapFlags) { if (mr[mipsReg].loc == ML_ARMREG || mr[mipsReg].loc == ML_ARMREG_IMM) { ARMReg armReg = mr[mipsReg].reg; if (ar[armReg].mipsReg != mipsReg) { - ERROR_LOG(JIT, "Register mapping out of sync! %i", mipsReg); + ERROR_LOG_REPORT(JIT, "Register mapping out of sync! %i", mipsReg); } if (mapFlags & MAP_DIRTY) { // Mapping dirty means the old imm value is invalid. @@ -250,13 +284,9 @@ allocate: // Still nothing. Let's spill a reg and goto 10. // TODO: Use age or something to choose which register to spill? // TODO: Spill dirty regs first? or opposite? - ARMReg bestToSpill = INVALID_REG; - for (int i = 0; i < allocCount; i++) { - ARMReg reg = allocOrder[i]; - if (ar[reg].mipsReg != MIPS_REG_INVALID && mr[ar[reg].mipsReg].spillLock) - continue; - bestToSpill = reg; - break; + ARMReg bestToSpill = FindBestToSpill(true); + if (bestToSpill == INVALID_REG) { + bestToSpill = FindBestToSpill(false); } if (bestToSpill != INVALID_REG) { @@ -266,7 +296,7 @@ allocate: } // Uh oh, we have all them spilllocked.... - ERROR_LOG(JIT, "Out of spillable registers at PC %08x!!!", mips_->pc); + ERROR_LOG_REPORT(JIT, "Out of spillable registers at PC %08x!!!", mips_->pc); return INVALID_REG; } @@ -318,17 +348,24 @@ void ArmRegCache::MapDirtyDirtyInIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, void ArmRegCache::FlushArmReg(ARMReg r) { if (ar[r].mipsReg == MIPS_REG_INVALID) { // Nothing to do, reg not mapped. + if (ar[r].isDirty) { + ERROR_LOG_REPORT(JIT, "Dirty but no mipsreg?"); + } return; } if (ar[r].mipsReg != MIPS_REG_INVALID) { - if (ar[r].isDirty && (mr[ar[r].mipsReg].loc == ML_ARMREG || mr[ar[r].mipsReg].loc == ML_ARMREG_IMM)) - emit_->STR(r, CTXREG, GetMipsRegOffset(ar[r].mipsReg)); - // IMMs won't be in an ARM reg. - mr[ar[r].mipsReg].loc = ML_MEM; - mr[ar[r].mipsReg].reg = INVALID_REG; - mr[ar[r].mipsReg].imm = 0; - } else { - ERROR_LOG(JIT, "Dirty but no mipsreg?"); + auto &mreg = mr[ar[r].mipsReg]; + if (mreg.loc == ML_ARMREG_IMM) { + // We know its immedate value, no need to STR now. + mreg.loc = ML_IMM; + mreg.reg = INVALID_REG; + } else { + if (ar[r].isDirty && mreg.loc == ML_ARMREG) + emit_->STR(r, CTXREG, GetMipsRegOffset(ar[r].mipsReg)); + mreg.loc = ML_MEM; + mreg.reg = INVALID_REG; + mreg.imm = 0; + } } ar[r].isDirty = false; ar[r].mipsReg = MIPS_REG_INVALID; @@ -359,7 +396,7 @@ void ArmRegCache::FlushR(MIPSGPReg r) { case ML_ARMREG: case ML_ARMREG_IMM: if (mr[r].reg == INVALID_REG) { - ERROR_LOG(JIT, "FlushR: MipsReg %d had bad ArmReg", r); + ERROR_LOG_REPORT(JIT, "FlushR: MipsReg %d had bad ArmReg", r); } if (ar[mr[r].reg].isDirty) { if (r != MIPS_REG_ZERO) { @@ -373,7 +410,7 @@ void ArmRegCache::FlushR(MIPSGPReg r) { case ML_ARMREG_AS_PTR: // Never dirty. if (ar[mr[r].reg].isDirty) { - ERROR_LOG(JIT, "ARMREG_AS_PTR cannot be dirty (yet)"); + ERROR_LOG_REPORT(JIT, "ARMREG_AS_PTR cannot be dirty (yet)"); } ar[mr[r].reg].mipsReg = MIPS_REG_INVALID; break; @@ -383,7 +420,7 @@ void ArmRegCache::FlushR(MIPSGPReg r) { break; default: - ERROR_LOG(JIT, "FlushR: MipsReg %d with invalid location %d", r, mr[r].loc); + ERROR_LOG_REPORT(JIT, "FlushR: MipsReg %d with invalid location %d", r, mr[r].loc); break; } mr[r].loc = ML_MEM; @@ -488,7 +525,7 @@ void ArmRegCache::FlushAll() { // Sanity check for (int i = 0; i < NUM_ARMREG; i++) { if (ar[i].mipsReg != MIPS_REG_INVALID) { - ERROR_LOG(JIT, "Flush fail: ar[%i].mipsReg=%i", i, ar[i].mipsReg); + ERROR_LOG_REPORT(JIT, "Flush fail: ar[%i].mipsReg=%i", i, ar[i].mipsReg); } } } @@ -519,7 +556,7 @@ bool ArmRegCache::IsImm(MIPSGPReg r) const { u32 ArmRegCache::GetImm(MIPSGPReg r) const { if (r == MIPS_REG_ZERO) return 0; if (mr[r].loc != ML_IMM && mr[r].loc != ML_ARMREG_IMM) { - ERROR_LOG(JIT, "Trying to get imm from non-imm register %i", r); + ERROR_LOG_REPORT(JIT, "Trying to get imm from non-imm register %i", r); } return mr[r].imm; } @@ -532,8 +569,12 @@ int ArmRegCache::GetMipsRegOffset(MIPSGPReg r) { return offsetof(MIPSState, hi); case MIPS_REG_LO: return offsetof(MIPSState, lo); + case MIPS_REG_FPCOND: + return offsetof(MIPSState, fpcond); + case MIPS_REG_VFPUCC: + return offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]); default: - ERROR_LOG(JIT, "bad mips register %i", r); + ERROR_LOG_REPORT(JIT, "bad mips register %i", r); return 0; // or what? } } @@ -559,7 +600,7 @@ ARMReg ArmRegCache::R(MIPSGPReg mipsReg) { if (mr[mipsReg].loc == ML_ARMREG || mr[mipsReg].loc == ML_ARMREG_IMM) { return (ARMReg)mr[mipsReg].reg; } else { - ERROR_LOG(JIT, "Reg %i not in arm reg. compilerPC = %08x", mipsReg, compilerPC_); + ERROR_LOG_REPORT(JIT, "Reg %i not in arm reg. compilerPC = %08x", mipsReg, compilerPC_); return INVALID_REG; // BAAAD } } @@ -568,7 +609,7 @@ ARMReg ArmRegCache::RPtr(MIPSGPReg mipsReg) { if (mr[mipsReg].loc == ML_ARMREG_AS_PTR) { return (ARMReg)mr[mipsReg].reg; } else { - ERROR_LOG(JIT, "Reg %i not in arm reg as pointer. compilerPC = %08x", mipsReg, compilerPC_); + ERROR_LOG_REPORT(JIT, "Reg %i not in arm reg as pointer. compilerPC = %08x", mipsReg, compilerPC_); return INVALID_REG; // BAAAD } } diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h index 9c21fab790..e1f7393a77 100644 --- a/Core/MIPS/ARM/ArmRegCache.h +++ b/Core/MIPS/ARM/ArmRegCache.h @@ -24,6 +24,8 @@ using namespace ArmGen; #define CTXREG (R10) +#define MEMBASEREG (R11) +#define DOWNCOUNTREG (R7) // R2 to R8: mapped MIPS regs // R9 = code pointers @@ -31,7 +33,7 @@ using namespace ArmGen; // R11 = base pointer enum { - TOTAL_MAPPABLE_MIPSREGS = 34, + TOTAL_MAPPABLE_MIPSREGS = 36, }; typedef int MIPSReg; @@ -124,6 +126,7 @@ private: const ARMReg *GetMIPSAllocationOrder(int &count); void MapRegTo(ARMReg reg, MIPSGPReg mipsReg, int mapFlags); int FlushGetSequential(MIPSGPReg startMipsReg, bool allowFlushImm); + ARMReg FindBestToSpill(bool unusedOnly); MIPSState *mips_; MIPSComp::ArmJitOptions *options_; diff --git a/Core/MIPS/ARM/ArmRegCacheFPU.cpp b/Core/MIPS/ARM/ArmRegCacheFPU.cpp index e7453dc4dd..7476795a70 100644 --- a/Core/MIPS/ARM/ArmRegCacheFPU.cpp +++ b/Core/MIPS/ARM/ArmRegCacheFPU.cpp @@ -16,14 +16,11 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "base/logging.h" -#include "Common/ArmEmitter.h" #include "Common/CPUDetect.h" #include "Core/MIPS/ARM/ArmRegCacheFPU.h" - using namespace ArmGen; - ArmRegCacheFPU::ArmRegCacheFPU(MIPSState *mips) : mips_(mips), vr(mr + 32) { if (cpu_info.bNEON) { numARMFpuReg_ = 32; @@ -52,15 +49,30 @@ void ArmRegCacheFPU::Start(MIPSAnalyst::AnalysisResults &stats) { static const ARMReg *GetMIPSAllocationOrder(int &count) { // We reserve S0-S1 as scratch. Can afford two registers. Maybe even four, which could simplify some things. static const ARMReg allocationOrder[] = { - S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15 + S2, S3, + S4, S5, S6, S7, + S8, S9, S10, S11, + S12, S13, S14, S15 }; // With NEON, we have many more. // In the future I plan to use S0-S7 (Q0-Q1) for FPU and S8 forwards (Q2-Q15, yes, 15) for VFPU. // VFPU will use NEON to do SIMD and it will be awkward to mix with FPU. + + // We should attempt to map scalars to low Q registers and wider things to high registers, + // as the NEON instructions are all 2-vector or 4-vector, they don't do scalar, we want to be + // able to use regular VFP instructions too. static const ARMReg allocationOrderNEON[] = { - S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, - S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31 + // Reserve four temp registers. Useful when building quads until we really figure out + // how to do that best. + S4, S5, S6, S7, // Q1 + S8, S9, S10, S11, // Q2 + S12, S13, S14, S15, // Q3 + S16, S17, S18, S19, // Q4 + S20, S21, S22, S23, // Q5 + S24, S25, S26, S27, // Q6 + S28, S29, S30, S31, // Q7 + // Q8-Q15 free for NEON tricks }; if (cpu_info.bNEON) { @@ -358,10 +370,17 @@ void ArmRegCacheFPU::FlushAll() { int ArmRegCacheFPU::GetMipsRegOffset(MIPSReg r) { // These are offsets within the MIPSState structure. First there are the GPRS, then FPRS, then the "VFPURs", then the VFPU ctrls. - if (r < 32 + 128 + NUM_TEMPS) - return (r + 32) << 2; - ERROR_LOG(JIT, "bad mips register %i, out of range", r); - return 0; // or what? + if (r < 0 || r > 32 + 128 + NUM_TEMPS) { + ERROR_LOG(JIT, "bad mips register %i, out of range", r); + return 0; // or what? + } + + if (r < 32 || r > 32 + 128) { + return (32 + r) << 2; + } else { + // r is between 32 and 128 + 32 + return (32 + 32 + voffset[r - 32]) << 2; + } } void ArmRegCacheFPU::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3, MIPSReg r4) { diff --git a/Core/MIPS/ARM/ArmRegCacheFPU.h b/Core/MIPS/ARM/ArmRegCacheFPU.h index 810a50f82f..bcb7da73e3 100644 --- a/Core/MIPS/ARM/ArmRegCacheFPU.h +++ b/Core/MIPS/ARM/ArmRegCacheFPU.h @@ -21,9 +21,9 @@ #include "../MIPS.h" #include "../MIPSAnalyst.h" -#include "Common/ArmEmitter.h" #include "Core/MIPS/ARM/ArmRegCache.h" #include "Core/MIPS/MIPSVFPUUtils.h" +#include "Common/ArmEmitter.h" using namespace ArmGen; @@ -48,7 +48,6 @@ struct FPURegMIPS { // If loc == ML_MEM, it's back in its location in the CPU context struct. }; - class ArmRegCacheFPU { public: @@ -79,16 +78,20 @@ public: // Returns an ARM register containing the requested MIPS register. ARMReg MapReg(MIPSReg reg, int mapFlags = 0); void MapInIn(MIPSReg rd, MIPSReg rs); - void MapInInV(int rt, int rs); - void MapDirtyInV(int rd, int rs, bool avoidLoad = true); - void MapDirtyInInV(int rd, int rs, int rt, bool avoidLoad = true); void MapDirty(MIPSReg rd); void MapDirtyIn(MIPSReg rd, MIPSReg rs, bool avoidLoad = true); void MapDirtyInIn(MIPSReg rd, MIPSReg rs, MIPSReg rt, bool avoidLoad = true); void FlushArmReg(ARMReg r); void FlushR(MIPSReg r); - void FlushV(MIPSReg r) { FlushR(r + 32); } void DiscardR(MIPSReg r); + + // VFPU register as single ARM VFP registers. Must not be used in the upcoming NEON mode! + void MapRegV(int vreg, int flags = 0); + void LoadToRegV(ARMReg armReg, int vreg); + void MapInInV(int rt, int rs); + void MapDirtyInV(int rd, int rs, bool avoidLoad = true); + void MapDirtyInInV(int rd, int rs, int rt, bool avoidLoad = true); + void FlushV(MIPSReg r) { FlushR(r + 32); } void DiscardV(MIPSReg r) { DiscardR(r + 32);} bool IsTempX(ARMReg r) const; @@ -99,14 +102,9 @@ public: ARMReg R(int preg); // Returns a cached register - // VFPU registers - + // VFPU registers as single VFP registers ARMReg V(int vreg) { return R(vreg + 32); } - void MapRegV(int vreg, int flags = 0); - - void LoadToRegV(ARMReg armReg, int vreg); - // NOTE: These require you to release spill locks manually! void MapRegsAndSpillLockV(int vec, VectorSize vsz, int flags); void MapRegsAndSpillLockV(const u8 *v, VectorSize vsz, int flags); diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index b3a09e3b8b..5dfe5d3366 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -183,7 +183,7 @@ void JitBlockCache::FinalizeBlock(int block_num, bool block_link) char buf[100]; sprintf(buf, "EmuCode%x", b.originalAddress); const u8* blockStart = blocks[block_num].checkedEntry; - op_write_native_code(agent, buf, (uint64_t)blockStart, blockStart, b.codeSize); + op_write_native_code(agent, buf, (uint64_t)blockStart, blockStart, b.normalEntry + b.codeSize - b.checkedEntry); #endif #ifdef USE_VTUNE @@ -194,7 +194,7 @@ void JitBlockCache::FinalizeBlock(int block_num, bool block_link) jmethod.class_file_name = ""; jmethod.source_file_name = __FILE__; jmethod.method_load_address = (void*)blocks[block_num].checkedEntry; - jmethod.method_size = b.codeSize; + jmethod.method_size = b.normalEntry + b.codeSize - b.checkedEntry; jmethod.line_number_size = 0; jmethod.method_name = b.blockName; iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); @@ -217,12 +217,19 @@ int binary_search(JitBlock blocks[], const u8 *baseoff, int imin, int imax) return -1; } -int JitBlockCache::GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const { +int JitBlockCache::GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad) const { if (!num_blocks || !MIPS_IS_EMUHACK(inst)) // definitely not a JIT block return -1; int off = (inst & MIPS_EMUHACK_VALUE_MASK); const u8 *baseoff = codeBlock_->GetBasePtr() + off; + if (baseoff < codeBlock_->GetBasePtr() || baseoff >= codeBlock_->GetCodePtr()) { + if (!ignoreBad) { + ERROR_LOG(JIT, "JitBlockCache: Invalid Emuhack Op %08x", inst.encoding); + } + return -1; + } + int bl = binary_search(blocks, baseoff, 0, num_blocks-1); if (blocks[bl].invalid) return -1; @@ -254,6 +261,21 @@ void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector block_numbers->push_back(i); } +u32 JitBlockCache::GetAddressFromBlockPtr(const u8 *ptr) const { + if (!codeBlock_->IsInSpace(ptr)) + return (u32)-1; + + for (int i = 0; i < num_blocks; ++i) { + const auto &b = blocks[i]; + if (!b.invalid && ptr >= b.checkedEntry && ptr < b.normalEntry + b.codeSize) { + return b.originalAddress; + } + } + + // It's in jit somewhere, but we must've deleted it. + return 0; +} + MIPSOpcode JitBlockCache::GetOriginalFirstOp(int block_num) { if (block_num >= num_blocks || block_num < 0) diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index eb417f09e6..55e0057b01 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -107,7 +107,9 @@ public: // Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap. // This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime. void GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers); - int GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const; + int GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad = false) const; + + u32 GetAddressFromBlockPtr(const u8 *ptr) const; MIPSOpcode GetOriginalFirstOp(int block_num); diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index ed18c309cc..1c121d09fc 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -21,6 +21,10 @@ struct JitBlock; +#ifdef USING_QT_UI +#undef emit +#endif + #if defined(PPC) #include "../PPC/PpcJit.h" #elif defined(ARM) diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index f7f13db6a4..2fa8ccda8c 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -123,7 +123,7 @@ namespace MIPSComp { prefixTFlag = PREFIX_KNOWN_DIRTY; prefixT = 0xE4; } - if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || VfpuWriteMask() != 0) { + if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0) { prefixDFlag = PREFIX_KNOWN_DIRTY; prefixD = 0x0; } diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index f1a4214e1f..bd9c580fea 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -44,6 +44,9 @@ MIPSState *currentMIPS = &mipsr4k; MIPSDebugInterface debugr4k(&mipsr4k); MIPSDebugInterface *currentDebugMIPS = &debugr4k; +u8 voffset[128]; +u8 fromvoffset[128]; + #ifndef M_LOG2E #define M_E 2.71828182845904523536f @@ -89,6 +92,70 @@ const float cst_constants[32] = { MIPSState::MIPSState() { MIPSComp::jit = 0; + + // Initialize vorder + + // This reordering of the VFPU registers in RAM means that instead of being like this: + + // 0x00 0x20 0x40 0x60 -> "columns", the most common direction + // 0x01 0x21 0x41 0x61 + // 0x02 0x22 0x42 0x62 + // 0x03 0x23 0x43 0x63 + + // 0x04 0x24 0x44 0x64 + // 0x06 0x26 0x45 0x65 + // .... + + // the VPU registers are effectively organized like this: + // 0x00 0x01 0x02 0x03 + // 0x04 0x05 0x06 0x07 + // 0x08 0x09 0x0a 0x0b + // .... + + // This is because the original indices look like this: + // 0XXMMMYY where M is the matrix number. + + // We will now map 0YYMMMXX to 0MMMXXYY. + + // Advantages: + // * Columns can be flushed and reloaded faster "at once" + // * 4x4 Matrices are contiguous in RAM, making them, too, fast-loadable in NEON + + // Disadvantages: + // * Extra indirection, can be confusing and slower (interpreter only) + // * Flushing and reloading row registers is now slower + + int i = 0; + for (int m = 0; m < 8; m++) { + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + voffset[m * 4 + x * 32 + y] = i++; + } + } + } + + // And the inverse. + for (int i = 0; i < 128; i++) { + fromvoffset[voffset[i]] = i; + } + + // Sanity check that things that should be ordered are ordered. + static const u8 firstThirtyTwo[] = { + 0x0, 0x20, 0x40, 0x60, + 0x1, 0x21, 0x41, 0x61, + 0x2, 0x22, 0x42, 0x62, + 0x3, 0x23, 0x43, 0x63, + + 0x4, 0x24, 0x44, 0x64, + 0x5, 0x25, 0x45, 0x65, + 0x6, 0x26, 0x46, 0x66, + 0x7, 0x27, 0x47, 0x67, + }; + for (int i = 0; i < (int)ARRAY_SIZE(firstThirtyTwo); i++) { + if (voffset[firstThirtyTwo[i]] != i) { + ERROR_LOG(CPU, "Wrong voffset order! %i: %i should have been %i", firstThirtyTwo[i], voffset[firstThirtyTwo[i]], i); + } + } } MIPSState::~MIPSState() @@ -134,7 +201,6 @@ void MIPSState::Reset() hi = 0; lo = 0; fpcond = 0; - fcr0 = 0; fcr31 = 0; debugCount = 0; currentMIPS = this; @@ -147,7 +213,7 @@ void MIPSState::Reset() } void MIPSState::DoState(PointerWrap &p) { - auto s = p.Section("MIPSState", 1); + auto s = p.Section("MIPSState", 1, 3); if (!s) return; @@ -161,7 +227,15 @@ void MIPSState::DoState(PointerWrap &p) { p.DoArray(r, sizeof(r) / sizeof(r[0])); p.DoArray(f, sizeof(f) / sizeof(f[0])); - p.DoArray(v, sizeof(v) / sizeof(v[0])); + if (s <= 2) { + float vtemp[128]; + p.DoArray(vtemp, sizeof(v) / sizeof(v[0])); + for (int i = 0; i < 128; i++) { + v[voffset[i]] = vtemp[i]; + } + } else { + p.DoArray(v, sizeof(v) / sizeof(v[0])); + } p.DoArray(vfpuCtrl, sizeof(vfpuCtrl) / sizeof(vfpuCtrl[0])); p.Do(pc); p.Do(nextPC); @@ -169,7 +243,10 @@ void MIPSState::DoState(PointerWrap &p) { p.Do(hi); p.Do(lo); p.Do(fpcond); - p.Do(fcr0); + if (s <= 1) { + u32 fcr0_unused = 0; + p.Do(fcr0_unused); + } p.Do(fcr31); p.Do(rng.m_w); p.Do(rng.m_z); @@ -204,7 +281,7 @@ void MIPSState::WriteFCR(int reg, int value) { if (reg == 31) { - fcr31 = value; + fcr31 = value & 0x0181FFFF; fpcond = (value >> 23) & 1; } else @@ -225,7 +302,7 @@ u32 MIPSState::ReadFCR(int reg) } else if (reg == 0) { - return fcr0; + return FCR0_VALUE; } else { diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index 7f311e8cb4..3714b04b88 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -68,6 +68,8 @@ enum MIPSGPReg // Not real regs, just for convenience/jit mapping. MIPS_REG_HI = 32, MIPS_REG_LO = 33, + MIPS_REG_FPCOND = 34, + MIPS_REG_VFPUCC = 35, }; enum @@ -113,6 +115,12 @@ enum VCondition VC_NS }; +// In memory, we order the VFPU registers differently. +// Games use columns a whole lot more than rows, and it would thus be good if columns +// were contiguous in memory. Also, matrices aren't but should be. +extern u8 voffset[128]; +extern u8 fromvoffset[128]; + class MIPSState { public: @@ -144,7 +152,6 @@ public: u32 hi; u32 lo; - u32 fcr0; u32 fcr31; //fpu control register u32 fpcond; // cache the cond flag of fcr31 (& 1 << 23) }; @@ -156,13 +163,15 @@ public: bool inDelaySlot; int llBit; // ll/sc - - + u32 temp; // can be used to save temporaries during calculations when we need more than R0 and R1 + GMRng rng; // VFPU hardware random number generator. Probably not the right type. // Debug stuff u32 debugCount; // can be used to count basic blocks before crashes, etc. + static const u32 FCR0_VALUE = 0x00003351; + void WriteFCR(int reg, int value); u32 ReadFCR(int reg); diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index c6cfd909f2..9d2c5314be 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -16,8 +16,11 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include +#include +#include "ext/cityhash/city.h" #include "Common/FileUtil.h" +#include "Core/Config.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSAnalyst.h" @@ -156,7 +159,7 @@ namespace MIPSAnalyst { { u32 start; u32 end; - u32 hash; + u64 hash; u32 size; bool isStraightLeaf; bool hasHash; @@ -166,7 +169,7 @@ namespace MIPSAnalyst { vector functions; - map hashToFunction; + map hashToFunction; void Shutdown() { @@ -215,29 +218,103 @@ namespace MIPSAnalyst { return true; } - void HashFunctions() - { - for (vector::iterator iter = functions.begin(); iter!=functions.end(); iter++) - { - Function &f=*iter; - u32 hash = 0x1337babe; - for (u32 addr = f.start; addr <= f.end; addr += 4) - { + void HashFunctions() { + std::vector buffer; + + for (auto iter = functions.begin(), end = functions.end(); iter != end; iter++) { + Function &f = *iter; + + // This is unfortunate. In case of emuhacks or relocs, we have to make a copy. + buffer.resize((f.end - f.start + 4) / 4); + size_t pos = 0; + for (u32 addr = f.start; addr <= f.end; addr += 4) { u32 validbits = 0xFFFFFFFF; MIPSOpcode instr = Memory::Read_Instruction(addr); MIPSInfo flags = MIPSGetInfo(instr); if (flags & IN_IMM16) - validbits&=~0xFFFF; + validbits &= ~0xFFFF; if (flags & IN_IMM26) - validbits&=~0x03FFFFFF; - hash = __rotl(hash,13); - hash ^= (instr&validbits); + validbits &= ~0x03FFFFFF; + buffer[pos++] = instr & validbits; } - f.hash=hash; - f.hasHash=true; + + f.hash = CityHash64((const char *) &buffer[0], buffer.size() * sizeof(u32)); + f.hasHash = true; } } + static const char *DefaultFunctionName(char buffer[256], u32 startAddr) { + sprintf(buffer, "z_un_%08x", startAddr); + return buffer; + } + + static bool IsDefaultFunction(const char *name) { + if (name == NULL) { + // Must be I guess? + return true; + } + + // Assume any z_un, not just the address, is a default func. + return !strncmp(name, "z_un_", strlen("z_un_")) || !strncmp(name, "u_un_", strlen("u_un_")); + } + + static u32 ScanAheadForJumpback(u32 fromAddr, u32 knownStart, u32 knownEnd) { + static const u32 MAX_AHEAD_SCAN = 0x1000; + // Maybe a bit high... just to make sure we don't get confused by recursive tail recursion. + static const u32 MAX_FUNC_SIZE = 0x20000; + + if (fromAddr > knownEnd + MAX_FUNC_SIZE) { + return INVALIDTARGET; + } + + // Code might jump halfway up to before fromAddr, but after knownEnd. + // In that area, there could be another jump up to the valid range. + // So we track that for a second scan. + u32 closestJumpbackAddr = INVALIDTARGET; + u32 closestJumpbackTarget = fromAddr; + + // We assume the furthest jumpback is within the func. + u32 furthestJumpbackAddr = INVALIDTARGET; + + for (u32 ahead = fromAddr; ahead < fromAddr + MAX_AHEAD_SCAN; ahead += 4) { + MIPSOpcode aheadOp = Memory::Read_Instruction(ahead); + u32 target = GetBranchTargetNoRA(ahead); + if (target == INVALIDTARGET && ((aheadOp & 0xFC000000) == 0x08000000)) { + target = GetJumpTarget(ahead); + } + + if (target != INVALIDTARGET) { + // Only if it comes back up to known code within this func. + if (target >= knownStart && target <= knownEnd) { + furthestJumpbackAddr = ahead; + } + // But if it jumps above fromAddr, we should scan that area too... + if (target < closestJumpbackTarget && target < fromAddr && target > knownEnd) { + closestJumpbackAddr = ahead; + closestJumpbackTarget = target; + } + } + } + + if (closestJumpbackAddr != INVALIDTARGET && furthestJumpbackAddr == INVALIDTARGET) { + for (u32 behind = closestJumpbackTarget; behind < fromAddr; behind += 4) { + MIPSOpcode behindOp = Memory::Read_Instruction(behind); + u32 target = GetBranchTargetNoRA(behind); + if (target == INVALIDTARGET && ((behindOp & 0xFC000000) == 0x08000000)) { + target = GetJumpTarget(behind); + } + + if (target != INVALIDTARGET) { + if (target >= knownStart && target <= knownEnd) { + furthestJumpbackAddr = closestJumpbackAddr; + } + } + } + } + + return furthestJumpbackAddr; + } + void ScanForFunctions(u32 startAddr, u32 endAddr /*, std::vector knownEntries*/) { Function currentFunction = {startAddr}; @@ -249,7 +326,16 @@ namespace MIPSAnalyst { for (addr = startAddr; addr <= endAddr; addr+=4) { SymbolInfo syminfo; if (symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION)) { - addr = syminfo.address + syminfo.size; + addr = syminfo.address + syminfo.size - 4; + + // We still need to insert the func for hashing purposes. + currentFunction.start = syminfo.address; + currentFunction.end = syminfo.address + syminfo.size - 4; + functions.push_back(currentFunction); + currentFunction.start = addr + 4; + furthestBranch = 0; + looking = false; + end = false; continue; } @@ -260,11 +346,37 @@ namespace MIPSAnalyst { if (target > furthestBranch) { furthestBranch = target; } + } else if ((op & 0xFC000000) == 0x08000000) { + u32 sureTarget = GetJumpTarget(addr); + // Check for a tail call. Might not even have a jr ra. + if (sureTarget != INVALIDTARGET && sureTarget < currentFunction.start) { + if (furthestBranch > addr) { + looking = true; + addr += 4; + } else { + end = true; + } + } else if (sureTarget != INVALIDTARGET && sureTarget > addr && sureTarget > furthestBranch) { + // A jump later. Probably tail, but let's check if it jumps back. + u32 knownEnd = furthestBranch == 0 ? addr : furthestBranch; + u32 jumpback = ScanAheadForJumpback(sureTarget, currentFunction.start, knownEnd); + if (jumpback != INVALIDTARGET && jumpback > addr && jumpback > knownEnd) { + furthestBranch = jumpback; + } else { + if (furthestBranch > addr) { + looking = true; + addr += 4; + } else { + end = true; + } + } + } } if (op == MIPS_MAKE_JR_RA()) { - if (furthestBranch >= addr) { + // If a branch goes to the jr ra, it's still ending here. + if (furthestBranch > addr) { looking = true; - addr+=4; + addr += 4; } else { end = true; } @@ -273,14 +385,22 @@ namespace MIPSAnalyst { if (looking) { if (addr >= furthestBranch) { u32 sureTarget = GetSureBranchTarget(addr); + // Regular j only, jals are to new funcs. + if (sureTarget == INVALIDTARGET && ((op & 0xFC000000) == 0x08000000)) { + sureTarget = GetJumpTarget(addr); + } + if (sureTarget != INVALIDTARGET && sureTarget < addr) { end = true; + } else if (sureTarget != INVALIDTARGET) { + // Okay, we have a downward jump. Might be an else or a tail call... + // If there's a jump back upward in spitting distance of it, it's an else. + u32 knownEnd = furthestBranch == 0 ? addr : furthestBranch; + u32 jumpback = ScanAheadForJumpback(sureTarget, currentFunction.start, knownEnd); + if (jumpback != INVALIDTARGET && jumpback > addr && jumpback > knownEnd) { + furthestBranch = jumpback; + } } - sureTarget = GetJumpTarget(addr); - if (sureTarget != INVALIDTARGET && sureTarget < addr && ((op&0xFC000000)==0x08000000)) { - end = true; - } - //end = true; } } if (end) { @@ -298,74 +418,112 @@ namespace MIPSAnalyst { currentFunction.end = addr + 4; functions.push_back(currentFunction); - for (vector::iterator iter = functions.begin(); iter!=functions.end(); iter++) { - (*iter).size = ((*iter).end-(*iter).start+4); + for (auto iter = functions.begin(); iter != functions.end(); iter++) { + iter->size = iter->end - iter->start + 4; char temp[256]; - sprintf(temp,"z_un_%08x",(*iter).start); - symbolMap.AddSymbol(std::string(temp).c_str(), (*iter).start,(*iter).end-(*iter).start+4,ST_FUNCTION); + symbolMap.AddFunction(DefaultFunctionName(temp, iter->start), iter->start, iter->end - iter->start + 4); } + HashFunctions(); + + if (g_Config.bFuncHashMap) { + LoadHashMap(GetSysDirectory(DIRECTORY_SYSTEM) + "knownfuncs.ini"); + StoreHashMap(GetSysDirectory(DIRECTORY_SYSTEM) + "knownfuncs.ini"); + } } struct HashMapFunc { char name[64]; - u32 hash; + u64 hash; u32 size; //number of bytes + + bool operator < (const HashMapFunc &other) const { + return hash < other.hash || (hash == other.hash && size < other.size); + } }; + std::set hashMap; - void StoreHashMap(const char *filename) { - FILE *file = File::OpenCFile(filename,"wb"); - u32 num = 0; - if (fwrite(&num,4,1,file) != 1) //fill in later - WARN_LOG(CPU, "Could not store hash map %s", filename); + void StoreHashMap(const std::string &filename) { + HashFunctions(); - for (vector::iterator iter = functions.begin(); iter!=functions.end(); iter++) { - Function &f=*iter; - if (f.hasHash && f.size >= 12) { - HashMapFunc temp; - memset(&temp, 0, sizeof(temp)); - strcpy(temp.name, f.name); - temp.hash=f.hash; - temp.size=f.size; - if (fwrite((char*)&temp, sizeof(temp), 1, file) != 1) { - WARN_LOG(CPU, "Could not store hash map %s", filename); - break; - } - num++; + FILE *file = File::OpenCFile(filename, "wt"); + if (!file) { + WARN_LOG(LOADER, "Could not store hash map: %s", filename.c_str()); + return; + } + + for (auto it = functions.begin(), end = functions.end(); it != end; ++it) { + const Function &f = *it; + // Small functions aren't very interesting. + if (!f.hasHash || f.size < 12) { + continue; + } + // Functions with default names aren't very interesting either. + const char *name = symbolMap.GetLabelName(f.start); + if (IsDefaultFunction(name)) { + continue; + } + + HashMapFunc mf = { "", f.hash, f.size }; + strncpy(mf.name, name, sizeof(mf.name) - 1); + hashMap.insert(mf); + } + + for (auto it = hashMap.begin(), end = hashMap.end(); it != end; ++it) { + const HashMapFunc &mf = *it; + if (fprintf(file, "%016llx:%d = %s\n", mf.hash, mf.size, mf.name) <= 0) { + WARN_LOG(LOADER, "Could not store hash map: %s", filename.c_str()); + break; } } - fseek(file, 0, SEEK_SET); - if (fwrite(&num, 4, 1, file) != 1) // fill in later - WARN_LOG(CPU, "Could not store hash map %s", filename); fclose(file); } - - void LoadHashMap(const char *filename) - { + void ApplyHashMap() { HashFunctions(); UpdateHashToFunctionMap(); - FILE *file = File::OpenCFile(filename, "rb"); - int num; - if (fread(&num, 4, 1, file) == 1) { - for (int i = 0; i < num; i++) { - HashMapFunc temp; - if(fread(&temp, sizeof(temp), 1, file) == 1) { - map::iterator iter = hashToFunction.find(temp.hash); - if (iter != hashToFunction.end()) { - //yay, found a function! - Function &f = *(iter->second); - if (f.size == temp.size) { - strcpy(f.name, temp.name); - f.hash=temp.hash; - f.size=temp.size; - } - } + for (auto mf = hashMap.begin(), end = hashMap.end(); mf != end; ++mf) { + auto iter = hashToFunction.find(mf->hash); + if (iter == hashToFunction.end()) { + continue; + } + + // Yay, found a function. + Function &f = *(iter->second); + if (f.hash == mf->hash && f.size == mf->size) { + strncpy(f.name, mf->name, sizeof(mf->name) - 1); + + const char *existingLabel = symbolMap.GetLabelName(f.start); + char defaultLabel[256]; + // If it was renamed, keep it. Only change the name if it's still the default. + if (existingLabel == NULL || !strcmp(existingLabel, DefaultFunctionName(defaultLabel, f.start))) { + symbolMap.SetLabelName(mf->name, f.start); } } } + } + + void LoadHashMap(const std::string &filename) { + FILE *file = File::OpenCFile(filename, "rt"); + if (!file) { + WARN_LOG(LOADER, "Could not load hash map: %s", filename.c_str()); + return; + } + + while (!feof(file)) { + HashMapFunc mf = { "" }; + if (fscanf(file, "%llx:%d = %63s\n", &mf.hash, &mf.size, mf.name) < 3) { + char temp[1024]; + fgets(temp, 1024, file); + continue; + } + + hashMap.insert(mf); + } fclose(file); + + ApplyHashMap(); } std::vector GetInputRegs(MIPSOpcode op) { diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index ed5555e489..4ae3c6be11 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -78,6 +78,8 @@ namespace MIPSAnalyst bool IsRegisterUsed(u32 reg, u32 addr); void ScanForFunctions(u32 startAddr, u32 endAddr); void CompileLeafs(); + void LoadHashMap(const std::string &filename); + void StoreHashMap(const std::string &filename); std::vector GetInputRegs(MIPSOpcode op); std::vector GetOutputRegs(MIPSOpcode op); diff --git a/Core/MIPS/MIPSCodeUtils.cpp b/Core/MIPS/MIPSCodeUtils.cpp index 49a42e4fa4..727469fccb 100644 --- a/Core/MIPS/MIPSCodeUtils.cpp +++ b/Core/MIPS/MIPSCodeUtils.cpp @@ -136,4 +136,8 @@ namespace MIPSCodeUtils bool IsVFPUBranch(MIPSOpcode op) { return (MIPSGetInfo(op) & (IS_VFPU | IS_CONDBRANCH)) == (IS_VFPU | IS_CONDBRANCH); } + + bool IsBranch(MIPSOpcode op) { + return (MIPSGetInfo(op) & IS_CONDBRANCH) == IS_CONDBRANCH; + } } diff --git a/Core/MIPS/MIPSCodeUtils.h b/Core/MIPS/MIPSCodeUtils.h index e356f3bf75..1568b99edd 100644 --- a/Core/MIPS/MIPSCodeUtils.h +++ b/Core/MIPS/MIPSCodeUtils.h @@ -58,4 +58,5 @@ namespace MIPSCodeUtils u32 GetJumpTarget(u32 addr); u32 GetSureBranchTarget(u32 addr); bool IsVFPUBranch(MIPSOpcode op); + bool IsBranch(MIPSOpcode op); } diff --git a/Core/MIPS/MIPSDebugInterface.cpp b/Core/MIPS/MIPSDebugInterface.cpp index d8e5962e35..0819eebc82 100644 --- a/Core/MIPS/MIPSDebugInterface.cpp +++ b/Core/MIPS/MIPSDebugInterface.cpp @@ -26,6 +26,17 @@ #include "../MIPS/MIPS.h" #include "../System.h" +enum ReferenceIndexType { + REF_INDEX_PC = 32, + REF_INDEX_HI = 33, + REF_INDEX_LO = 34, + REF_INDEX_FPU = 0x1000, + REF_INDEX_FPU_INT = 0x2000, + REF_INDEX_VFPU = 0x4000, + REF_INDEX_VFPU_INT = 0x8000, + REF_INDEX_IS_FLOAT = REF_INDEX_FPU | REF_INDEX_VFPU, +}; + class MipsExpressionFunctions: public IExpressionFunctions { @@ -37,35 +48,93 @@ public: for (int i = 0; i < 32; i++) { char reg[8]; - sprintf(reg,"r%d",i); + sprintf(reg, "r%d", i); - if (strcasecmp(str,reg) == 0 || strcasecmp(str,cpu->GetRegName(0,i)) == 0) + if (strcasecmp(str, reg) == 0 || strcasecmp(str, cpu->GetRegName(0, i)) == 0) { referenceIndex = i; return true; } + else if (strcasecmp(str, cpu->GetRegName(1, i)) == 0) + { + referenceIndex = REF_INDEX_FPU | i; + return true; + } + + sprintf(reg, "fi%d", i); + if (strcasecmp(str, reg) == 0) + { + referenceIndex = REF_INDEX_FPU_INT | i; + return true; + } } - if (strcasecmp(str,"pc") == 0) + for (int i = 0; i < 128; i++) { - referenceIndex = 32; + if (strcasecmp(str, cpu->GetRegName(2, i)) == 0) + { + referenceIndex = REF_INDEX_VFPU | i; + return true; + } + + char reg[8]; + sprintf(reg, "vi%d", i); + if (strcasecmp(str, reg) == 0) + { + referenceIndex = REF_INDEX_VFPU_INT | i; + return true; + } + } + + if (strcasecmp(str, "pc") == 0) + { + referenceIndex = REF_INDEX_PC; return true; - } + } + + if (strcasecmp(str, "hi") == 0) + { + referenceIndex = REF_INDEX_HI; + return true; + } + + if (strcasecmp(str, "lo") == 0) + { + referenceIndex = REF_INDEX_LO; + return true; + } return false; } virtual bool parseSymbol(char* str, uint32& symbolValue) { - return cpu->getSymbolValue(str,symbolValue); + return symbolMap.GetLabelValue(str,symbolValue); } virtual uint32 getReferenceValue(uint32 referenceIndex) { - if (referenceIndex < 32) return cpu->GetRegValue(0,referenceIndex); - if (referenceIndex == 32) return cpu->GetPC(); + if (referenceIndex < 32) + return cpu->GetRegValue(0, referenceIndex); + if (referenceIndex == REF_INDEX_PC) + return cpu->GetPC(); + if (referenceIndex == REF_INDEX_HI) + return cpu->GetHi(); + if (referenceIndex == REF_INDEX_LO) + return cpu->GetLo(); + if ((referenceIndex & ~(REF_INDEX_FPU | REF_INDEX_FPU_INT)) < 32) + return cpu->GetRegValue(1, referenceIndex & ~(REF_INDEX_FPU | REF_INDEX_FPU_INT)); + if ((referenceIndex & ~(REF_INDEX_VFPU | REF_INDEX_VFPU_INT)) < 128) + return cpu->GetRegValue(2, referenceIndex & ~(REF_INDEX_VFPU | REF_INDEX_VFPU_INT)); return -1; } + + virtual ExpressionType getReferenceType(uint32 referenceIndex) { + if (referenceIndex & REF_INDEX_IS_FLOAT) { + return EXPR_TYPE_FLOAT; + } + return EXPR_TYPE_UINT; + } virtual bool getMemoryValue(uint32 address, int size, uint32& dest, char* error) { @@ -152,8 +221,8 @@ void MIPSDebugInterface::toggleBreakpoint(unsigned int address) int MIPSDebugInterface::getColor(unsigned int address) { int colors[6] = {0xe0FFFF,0xFFe0e0,0xe8e8FF,0xFFe0FF,0xe0FFe0,0xFFFFe0}; - int n=symbolMap.GetSymbolNum(address); - if (n==-1 || symbolMap.GetSymbolSize(n) < 4) return 0xFFFFFF; + int n=symbolMap.GetFunctionNum(address); + if (n==-1) return 0xFFFFFF; return colors[n%6]; } const char *MIPSDebugInterface::getDescription(unsigned int address) @@ -161,16 +230,6 @@ const char *MIPSDebugInterface::getDescription(unsigned int address) return symbolMap.GetDescription(address); } -const char *MIPSDebugInterface::findSymbolForAddress(unsigned int address) -{ - return symbolMap.getDirectSymbol(address); -} - -bool MIPSDebugInterface::getSymbolValue(char* symbol, u32& dest) -{ - return symbolMap.getSymbolValue(symbol,dest); -} - bool MIPSDebugInterface::initExpression(const char* exp, PostfixExpression& dest) { MipsExpressionFunctions funcs(this); diff --git a/Core/MIPS/MIPSDebugInterface.h b/Core/MIPS/MIPSDebugInterface.h index 26ee3e9d6f..20ae2a74fd 100644 --- a/Core/MIPS/MIPSDebugInterface.h +++ b/Core/MIPS/MIPSDebugInterface.h @@ -40,8 +40,6 @@ public: virtual void runToBreakpoint(); virtual int getColor(unsigned int address); virtual const char *getDescription(unsigned int address); - virtual const char *findSymbolForAddress(unsigned int address); - virtual bool getSymbolValue(char* symbol, u32& dest); virtual bool initExpression(const char* exp, PostfixExpression& dest); virtual bool parseExpression(PostfixExpression& exp, u32& dest); @@ -103,12 +101,13 @@ public: { case 0: return cpu->r[index]; + case 1: memcpy(&temp, &cpu->f[index], 4); return temp; case 2: - memcpy(&temp, &cpu->v[index], 4); + memcpy(&temp, &cpu->v[voffset[index]], 4); return temp; default: @@ -121,7 +120,8 @@ public: switch (cat) { case 0: - cpu->r[index] = value; + if (index != 0) + cpu->r[index] = value; break; case 1: @@ -129,7 +129,7 @@ public: break; case 2: - memcpy(&cpu->v[index], &value, 4); + memcpy(&cpu->v[voffset[index]], &value, 4); break; default: diff --git a/Core/MIPS/MIPSDis.cpp b/Core/MIPS/MIPSDis.cpp index 5eac7c6173..83a80da535 100644 --- a/Core/MIPS/MIPSDis.cpp +++ b/Core/MIPS/MIPSDis.cpp @@ -61,6 +61,14 @@ namespace MIPSDis sprintf(out, "%s\t --- unknown ---", MIPSGetName(op)); } + void Dis_Cache(MIPSOpcode op, char *out) + { + int imm = (s16)(op & 0xFFFF); + int rs = _RS; + int func = (op >> 16) & 0x1F; + sprintf(out, "%s\tfunc=%i, %s(%s)", MIPSGetName(op), func, RN(rs), SignedHex(imm)); + } + void Dis_mxc1(MIPSOpcode op, char *out) { int fs = _FS; diff --git a/Core/MIPS/MIPSDis.h b/Core/MIPS/MIPSDis.h index 5a706f5919..ad080de03d 100644 --- a/Core/MIPS/MIPSDis.h +++ b/Core/MIPS/MIPSDis.h @@ -34,6 +34,7 @@ namespace MIPSDis void Dis_RelBranch2(MIPSOpcode op, char *out); void Dis_RelBranch(MIPSOpcode op, char *out); void Dis_Generic(MIPSOpcode op, char *out); + void Dis_Cache(MIPSOpcode op, char *out); void Dis_IType(MIPSOpcode op, char *out); void Dis_IType1(MIPSOpcode op, char *out); void Dis_ITypeMem(MIPSOpcode op, char *out); diff --git a/Core/MIPS/MIPSDisVFPU.cpp b/Core/MIPS/MIPSDisVFPU.cpp index e76f7a49e6..bea774bff9 100644 --- a/Core/MIPS/MIPSDisVFPU.cpp +++ b/Core/MIPS/MIPSDisVFPU.cpp @@ -137,6 +137,14 @@ namespace MIPSDis sprintf(out, "%s%s\t%s, %s",name,vr>127?"c":"", RN(rt), VN(vr, V_Single)); } + void Dis_Vmftvc(MIPSOpcode op, char *out) + { + int vr = op & 0xFF; + int vs = _VS; + const char *name = MIPSGetName(op); + sprintf(out, "%s\t%s, %s", name, VN(vs, V_Single), VN(vr, V_Single)); + } + void Dis_VPFXST(MIPSOpcode op, char *out) { int data = op & 0xFFFFF; @@ -184,7 +192,8 @@ namespace MIPSDis strcat(out, satNames[sat]); if (mask) strcat(out, "M"); - strcat(out, " "); + if (i < 4 - 1) + strcat(out, ", "); } } @@ -202,7 +211,7 @@ namespace MIPSDis else if (type == 7) sprintf(out, "%s\t%s, %f", name, VN(vt, V_Single), Float16ToFloat32((u16)imm)); else - sprintf(out, "ARGH"); + sprintf(out, "%s\tARGH", name); } void Dis_Vcst(MIPSOpcode op, char *out) @@ -271,9 +280,20 @@ namespace MIPSDis int vs = _VS; int vt = _VT; MatrixSize sz = GetMtxSize(op); + // TODO: Xpose? sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),MN(vd, sz),MN(Xpose(vs),sz),MN(vt,sz)); } + void Dis_Vmscl(MIPSOpcode op, char *out) + { + const char *name = MIPSGetName(op); + int vd = _VD; + int vs = _VS; + int vt = _VT; + MatrixSize sz = GetMtxSize(op); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs, sz), VN(vt, V_Single)); + } + void Dis_VectorDot(MIPSOpcode op, char *out) { const char *name = MIPSGetName(op); @@ -351,14 +371,13 @@ namespace MIPSDis int imm3 = (op>>16)&7; if (tf > 1) { - sprintf(out, "Vcmov\tARGH%i", tf); + sprintf(out, "%s\tARGH%i", name, tf); return; } if (imm3<6) sprintf(out, "%s%s%s\t%s, %s, CC[%i]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz), imm3); else if (imm3 == 6) sprintf(out, "%s%s%s\t%s, %s, CC[...]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz)); - } void Dis_Vfad(MIPSOpcode op, char *out) @@ -505,6 +524,68 @@ namespace MIPSDis sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, dsz),VN(vs, sz)); } + void Dis_Vwbn(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSize(op); + + int vd = _VD; + int vs = _VS; + int imm = (int)((op >> 16) & 0xFF); + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s, %s, %d", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm); + } + + void Dis_Vf2h(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSize(op); + VectorSize dsz = GetHalfVectorSize(sz); + if (((op>>16)&3)==0) + dsz = V_Single; + + int vd = _VD; + int vs = _VS; + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + } + + void Dis_Vh2f(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSize(op); + VectorSize dsz = GetDoubleVectorSize(sz); + + int vd = _VD; + int vs = _VS; + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + } + + void Dis_ColorConv(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSize(op); + VectorSize dsz = GetHalfVectorSize(sz); + + int vd = _VD; + int vs = _VS; + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + } + + void Dis_Vrnds(MIPSOpcode op, char *out) + { + int vd = _VD; + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s", name, VSuff(op), VN(vd, V_Single)); + } + + void Dis_VrndX(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSize(op); + + int vd = _VD; + const char *name = MIPSGetName(op); + sprintf(out, "%s%s\t%s", name, VSuff(op), VN(vd, sz)); + } + void Dis_VBranch(MIPSOpcode op, char *out) { u32 off = disPC; diff --git a/Core/MIPS/MIPSDisVFPU.h b/Core/MIPS/MIPSDisVFPU.h index dbb1aef3f0..e5072b61aa 100644 --- a/Core/MIPS/MIPSDisVFPU.h +++ b/Core/MIPS/MIPSDisVFPU.h @@ -24,6 +24,7 @@ extern u32 disPC; namespace MIPSDis { void Dis_Mftv(MIPSOpcode op, char *out); + void Dis_Vmftvc(MIPSOpcode op, char *out); void Dis_SV(MIPSOpcode op, char *out); void Dis_SVQ(MIPSOpcode op, char *out); @@ -33,6 +34,7 @@ namespace MIPSDis void Dis_MatrixSet2(MIPSOpcode op, char *out); void Dis_MatrixSet3(MIPSOpcode op, char *out); void Dis_MatrixMult(MIPSOpcode op, char *out); + void Dis_Vmscl(MIPSOpcode op, char *out); void Dis_VectorDot(MIPSOpcode op, char *out); void Dis_Vfad(MIPSOpcode op, char *out); @@ -56,5 +58,12 @@ namespace MIPSDis void Dis_Vf2i(MIPSOpcode op, char *out); void Dis_Vi2x(MIPSOpcode op, char *out); void Dis_Vs2i(MIPSOpcode op, char *out); + void Dis_Vwbn(MIPSOpcode op, char *out); + void Dis_Vf2h(MIPSOpcode op, char *out); + void Dis_Vh2f(MIPSOpcode op, char *out); + void Dis_Vrnds(MIPSOpcode op, char *out); + void Dis_VrndX(MIPSOpcode op, char *out); + void Dis_ColorConv(MIPSOpcode op, char *out); + void Dis_VBranch(MIPSOpcode op, char *out); } diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index 99c2fe075f..471a6f0e6b 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -26,6 +26,7 @@ #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSInt.h" #include "Core/MIPS/MIPSTables.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/Reporting.h" #include "Core/Config.h" #include "Core/HLE/HLE.h" @@ -98,8 +99,6 @@ int MIPS_SingleStep() return 1; } - - u32 MIPS_GetNextPC() { if (mipsr4k.inDelaySlot) @@ -108,13 +107,11 @@ u32 MIPS_GetNextPC() return mipsr4k.pc + 4; } - void MIPS_ClearDelaySlot() { mipsr4k.inDelaySlot = false; } - namespace MIPSInt { void Int_Cache(MIPSOpcode op) @@ -124,8 +121,20 @@ namespace MIPSInt int addr = R(rs) + imm; int func = (op >> 16) & 0x1F; - // It appears that a cache line is 0x40 (64) bytes. + // It appears that a cache line is 0x40 (64) bytes, loops in games + // issue the cache instruction at that interval. + + // These codes might be PSP-specific, they don't match regular MIPS cache codes very well switch (func) { + // Icache + case 8: + // Invalidate the instruction cache at this address + if (MIPSComp::jit) { + MIPSComp::jit->ClearCacheAt(addr, 0x40); + } + break; + + // Dcache case 24: // "Create Dirty Exclusive" - for avoiding a cacheline fill before writing to it. // Will cause garbage on the real machine so we just ignore it, the app will overwrite the cacheline. @@ -133,13 +142,13 @@ namespace MIPSInt case 25: // Hit Invalidate - zaps the line if present in cache. Should not writeback???? scary. // No need to do anything. break; - case 27: // D-cube. Hit Writeback Invalidate. + case 27: // D-cube. Hit Writeback Invalidate. Tony Hawk Underground 2 break; - case 30: // GTA LCS, a lot. Fill (prefetch). + case 30: // GTA LCS, a lot. Fill (prefetch). Tony Hawk Underground 2 break; default: - DEBUG_LOG(CPU,"cache instruction affecting %08x : function %i", addr, func); + DEBUG_LOG(CPU, "cache instruction affecting %08x : function %i", addr, func); } PC += 4; @@ -871,7 +880,7 @@ namespace MIPSInt case 13: case 14: case 15: - if (my_isinf(F(fs)) || my_isnan(F(fs))) + if (my_isnanorinf(F(fs))) { FsI(fd) = my_isinf(F(fs)) && F(fs) < 0.0f ? -2147483648LL : 2147483647LL; break; @@ -887,7 +896,7 @@ namespace MIPSInt case 32: F(fd) = (float)FsI(fs); break; //cvt.s.w case 36: - if (my_isinf(F(fs)) || my_isnan(F(fs))) + if (my_isnanorinf(F(fs))) { FsI(fd) = my_isinf(F(fs)) && F(fs) < 0.0f ? -2147483648LL : 2147483647LL; break; diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index e800ea668f..af4edf4a6b 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -52,8 +52,8 @@ #include #define R(i) (currentMIPS->r[i]) -#define V(i) (currentMIPS->v[i]) -#define VI(i) (currentMIPS->vi[i]) +#define V(i) (currentMIPS->v[voffset[i]]) +#define VI(i) (currentMIPS->vi[voffset[i]]) #define FI(i) (currentMIPS->fi[i]) #define FsI(i) (currentMIPS->fs[i]) #define PC (currentMIPS->pc) @@ -107,7 +107,7 @@ inline float nanclamp(float f, float lower, float upper) } -void ApplyPrefixST(float *v, u32 data, VectorSize size) +void ApplyPrefixST(float *r, u32 data, VectorSize size) { // Possible optimization shortcut: if (data == 0xe4) @@ -119,7 +119,7 @@ void ApplyPrefixST(float *v, u32 data, VectorSize size) for (int i = 0; i < n; i++) { - origV[i] = v[i]; + origV[i] = r[i]; } for (int i = 0; i < n; i++) @@ -141,17 +141,17 @@ void ApplyPrefixST(float *v, u32 data, VectorSize size) regnum = 0; } - v[i] = origV[regnum]; + r[i] = origV[regnum]; if (abs) - v[i] = fabs(v[i]); + r[i] = fabs(r[i]); } else { - v[i] = constantArray[regnum + (abs<<2)]; + r[i] = constantArray[regnum + (abs<<2)]; } if (negate) - v[i] = -v[i]; + r[i] = -r[i]; } } @@ -1193,6 +1193,7 @@ namespace MIPSInt ReadVector(s, sz, vs); ApplySwizzleS(s, sz); ReadVector(t, sz, vt); + // TODO: Does t have swizzle? d[0] = s[0] * t[1] - s[1] * t[0]; ApplyPrefixD(d, sz); WriteVector(d, V_Single, vd); @@ -1515,12 +1516,12 @@ namespace MIPSInt case VC_EZ: c = s[i] == 0.0f || s[i] == -0.0f; break; case VC_EN: c = my_isnan(s[i]); break; case VC_EI: c = my_isinf(s[i]); break; - case VC_ES: c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection + case VC_ES: c = my_isnanorinf(s[i]); break; // Tekken Dark Resurrection case VC_NZ: c = s[i] != 0; break; case VC_NN: c = !my_isnan(s[i]); break; case VC_NI: c = !my_isinf(s[i]); break; - case VC_NS: c = !my_isnan(s[i]) && !my_isinf(s[i]); break; + case VC_NS: c = !(my_isnanorinf(s[i])); break; // How about t[i] ? default: _dbg_assert_msg_(CPU,0,"Unsupported vcmp condition code %d", cond); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index b8c437e3bf..3bc8cbedba 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -147,7 +147,7 @@ const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ............... INVALID, INVALID, INSTR("swr", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM|MEMTYPE_WORD), - INSTR("cache", &Jit::Comp_Cache, Dis_Generic, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_OTHER), + INSTR("cache", &Jit::Comp_Cache, Dis_Cache, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_OTHER), //48 INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD), INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|MEMTYPE_FLOAT), @@ -537,9 +537,9 @@ const MIPSInstruction tableVFPU1[8] = // 011001 xxx ....... . ....... . ....... INSTR("vdot", &Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vscl", &Jit::Comp_VScl, Dis_VScl, Int_VScl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INVALID, - INSTR("vhdp", &Jit::Comp_VHdp, Dis_Generic, Int_VHdp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vhdp", &Jit::Comp_VHdp, Dis_VectorDot, Int_VHdp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrs", &Jit::Comp_VCrs, Dis_Vcrs, Int_Vcrs, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vdet", &Jit::Comp_VDet, Dis_Generic, Int_Vdet, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vdet", &Jit::Comp_VDet, Dis_VectorDot, Int_Vdet, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INVALID, }; @@ -578,22 +578,23 @@ const MIPSInstruction tableVFPU4Jump[32] = // 110100 xxxxx ..... . ....... . ... INVALID, //24 - 110100 11 ........ . ....... . ....... // TODO: Flags may not be correct (prefixes, etc.) - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), - INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU), }; const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... . ....... { - INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + // TODO disasm + INSTR("vrnds", &Jit::Comp_Generic, Dis_Vrnds, Int_Vrnds, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndi", &Jit::Comp_Generic, Dis_VrndX, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndf1", &Jit::Comp_Generic, Dis_VrndX, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndf2", &Jit::Comp_Generic, Dis_VrndX, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INVALID, INVALID, INVALID, INVALID, //8 @@ -604,8 +605,8 @@ const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... . ....... //16 INVALID, INVALID, - INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vh2f", &Jit::Comp_Vh2f, Dis_Generic, Int_Vh2f, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vf2h", &Jit::Comp_Generic, Dis_Vf2h, Int_Vf2h, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vh2f", &Jit::Comp_Vh2f, Dis_Vh2f, Int_Vh2f, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INVALID, INVALID, @@ -691,10 +692,10 @@ const MIPSInstruction tableVFPU6[32] = // 111100 xxxxx ..... . ....... . ....... INSTR("v(h)tfm4", &Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("v(h)tfm4", &Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), //16 - INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Vmscl, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Vmscl, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Vmscl, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl", &Jit::Comp_Vmscl, Dis_Vmscl, Int_Vmscl, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrsp.t/vqmul.q", &Jit::Comp_VCrossQuat, Dis_CrossQuat, Int_CrossQuat, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrsp.t/vqmul.q", &Jit::Comp_VCrossQuat, Dis_CrossQuat, Int_CrossQuat, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), @@ -737,7 +738,7 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . ....... INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), //4 - INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // one's complement + INSTR("vocp", &Jit::Comp_Vocp, Dis_Vbfy, Int_Vocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // one's complement INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), INSTR("vfad", &Jit::Comp_Vhoriz, Dis_Vfad, Int_Vfad, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // TODO: Flags may not be correct (prefixes, etc.) @@ -757,9 +758,9 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . ....... //16 // TODO: Flags may not be correct (prefixes, etc.) - INSTR("vmfvc", &Jit::Comp_Generic, Dis_Generic, Int_Vmfvc, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vmfvc", &Jit::Comp_Generic, Dis_Vmftvc, Int_Vmfvc, IN_OTHER|OUT_OTHER|IS_VFPU), // TODO: Flags may not be correct (prefixes, etc.) - INSTR("vmtvc", &Jit::Comp_Generic, Dis_Generic, Int_Vmtvc, IN_OTHER|OUT_OTHER|IS_VFPU), + INSTR("vmtvc", &Jit::Comp_Generic, Dis_Vmftvc, Int_Vmtvc, IN_OTHER|OUT_OTHER|IS_VFPU), INVALID, INVALID, @@ -767,9 +768,9 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . ....... INVALID, INVALID, INVALID, INVALID, //24 INVALID, - INSTR("vt4444", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vt5551", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), - INSTR("vt5650", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vt4444", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vt5551", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), + INSTR("vt5650", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), //28 INVALID, INVALID, INVALID, INVALID, diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 36b51e4a7e..986fd61483 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -86,6 +86,7 @@ struct MIPSInfo { #define VFPU_NO_PREFIX 0x10000000 #define IS_VFPU 0x20000000 +#define IS_FPU 0x40000000 #ifndef CDECL #define CDECL diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 5b63141de4..d503fd4313 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -22,8 +22,8 @@ #include -#define V(i) (currentMIPS->v[i]) -#define VI(i) (currentMIPS->vi[i]) +#define V(i) (currentMIPS->v[voffset[i]]) +#define VI(i) (currentMIPS->vi[voffset[i]]) void GetVectorRegs(u8 regs[4], VectorSize N, int vectorReg) { int mtx = (vectorReg >> 2) & 7; @@ -226,6 +226,17 @@ VectorSize GetHalfVectorSize(VectorSize sz) } } +VectorSize GetDoubleVectorSize(VectorSize sz) +{ + switch (sz) + { + case V_Single: return V_Pair; + case V_Pair: return V_Quad; + default: + return V_Pair; + } +} + VectorSize GetVecSize(MIPSOpcode op) { int a = (op>>7)&1; @@ -248,7 +259,7 @@ MatrixSize GetMtxSize(MIPSOpcode op) a += (b<<1); switch (a) { - case 0: ERROR_LOG_REPORT(CPU, "Unexpected matrix size 1x1."); return M_2x2; + case 0: return M_4x4; // This error pretty much only happens in disassembly of junk: // ERROR_LOG_REPORT(CPU, "Unexpected matrix size 1x1."); return M_2x2; case 1: return M_2x2; case 2: return M_3x3; case 3: return M_4x4; diff --git a/Core/MIPS/MIPSVFPUUtils.h b/Core/MIPS/MIPSVFPUUtils.h index 68e4a75153..f98e76cefc 100644 --- a/Core/MIPS/MIPSVFPUUtils.h +++ b/Core/MIPS/MIPSVFPUUtils.h @@ -68,6 +68,7 @@ inline int GetMtx(int matrixReg) { VectorSize GetVecSize(MIPSOpcode op); MatrixSize GetMtxSize(MIPSOpcode op); VectorSize GetHalfVectorSize(VectorSize sz); +VectorSize GetDoubleVectorSize(VectorSize sz); int GetNumVectorElements(VectorSize sz); int GetMatrixSide(MatrixSize sz); const char *GetVectorNotation(int reg, VectorSize size); diff --git a/Core/MIPS/PPC/PpcCompVFPU.cpp b/Core/MIPS/PPC/PpcCompVFPU.cpp index cfde013261..80cdd53926 100644 --- a/Core/MIPS/PPC/PpcCompVFPU.cpp +++ b/Core/MIPS/PPC/PpcCompVFPU.cpp @@ -1117,4 +1117,8 @@ namespace MIPSComp void Jit::Comp_Vsgn(MIPSOpcode op) { DISABLE; } -} \ No newline at end of file + void Jit::Comp_Vocp(MIPSOpcode op) { + DISABLE; + } +} + diff --git a/Core/MIPS/PPC/PpcJit.h b/Core/MIPS/PPC/PpcJit.h index aef427332b..c3a2587262 100644 --- a/Core/MIPS/PPC/PpcJit.h +++ b/Core/MIPS/PPC/PpcJit.h @@ -237,6 +237,7 @@ namespace MIPSComp void Comp_Vfim(MIPSOpcode op); void Comp_VCrossQuat(MIPSOpcode op); void Comp_Vsgn(MIPSOpcode op); + void Comp_Vocp(MIPSOpcode op); // Utility compilation functions @@ -293,6 +294,10 @@ namespace MIPSComp void Compile(u32 em_address); // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); + bool IsInDispatch(const u8 *p) { + return IsInSpace(p); + } + PpcJitOptions jo; PpcJitState js; diff --git a/Core/MIPS/PPC/PpcRegCacheFPU.cpp b/Core/MIPS/PPC/PpcRegCacheFPU.cpp index 9646c389f9..dd2e53322a 100644 --- a/Core/MIPS/PPC/PpcRegCacheFPU.cpp +++ b/Core/MIPS/PPC/PpcRegCacheFPU.cpp @@ -344,10 +344,17 @@ void PpcRegCacheFPU::FlushAll() { int PpcRegCacheFPU::GetMipsRegOffset(MIPSReg r) { // These are offsets within the MIPSState structure. First there are the GPRS, then FPRS, then the "VFPURs", then the VFPU ctrls. - if (r < 32 + 128 + NUM_TEMPS) - return (r + 32) << 2; - ERROR_LOG(JIT, "bad mips register %i, out of range", r); - return 0; // or what? + if (r < 0 || r > 32 + 128 + NUM_TEMPS) { + ERROR_LOG(JIT, "bad mips register %i, out of range", r); + return 0; // or what? + } + + if (r < 32 || r > 32 + 128) { + return (32 + r) << 2; + } else { + // r is between 32 and 128 + 32 + return (32 + 32 + voffset[r - 32]) << 2; + } } void PpcRegCacheFPU::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3, MIPSReg r4) { diff --git a/Core/MIPS/x86/CompALU.cpp b/Core/MIPS/x86/CompALU.cpp index 8a6851b462..8567224b03 100644 --- a/Core/MIPS/x86/CompALU.cpp +++ b/Core/MIPS/x86/CompALU.cpp @@ -643,7 +643,8 @@ namespace MIPSComp gpr.Lock(rs, rt); gpr.MapReg(rt, true, true); AND(32, gpr.R(rt), Imm32(destmask)); - OR(32, gpr.R(rt), Imm32(inserted)); + if (inserted != 0) + OR(32, gpr.R(rt), Imm32(inserted)); gpr.UnlockAll(); } else diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 574045ac46..d2ae447c34 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -150,7 +150,7 @@ static CCFlags FlipCCFlag(CCFlags flag) case CC_LE: return CC_NLE; case CC_NLE: return CC_LE; } - ERROR_LOG_REPORT(JIT, false, "FlipCCFlag: Unexpected CC flag: %d", flag); + ERROR_LOG_REPORT(JIT, "FlipCCFlag: Unexpected CC flag: %d", flag); return CC_O; } @@ -165,6 +165,106 @@ bool Jit::PredictTakeBranch(u32 targetAddr, bool likely) { return targetAddr > js.compilerPC; } +void Jit::CompBranchExits(CCFlags cc, u32 targetAddr, u32 notTakenAddr, bool delaySlotIsNice, bool likely, bool andLink) { + // We may want to try to continue along this branch a little while, to reduce reg flushing. + if (CanContinueBranch()) + { + bool predictTakeBranch = PredictTakeBranch(targetAddr, likely); + if (predictTakeBranch) + cc = FlipCCFlag(cc); + + Gen::FixupBranch ptr; + RegCacheState state; + if (!likely) + { + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE); + ptr = J_CC(cc, true); + GetStateAndFlushAll(state); + } + else + { + ptr = J_CC(cc, true); + if (predictTakeBranch) + GetStateAndFlushAll(state); + else + CompileDelaySlot(DELAYSLOT_FLUSH); + } + + if (predictTakeBranch) + { + // We flipped the cc, the not taken case is first. + CONDITIONAL_LOG_EXIT(notTakenAddr); + WriteExit(notTakenAddr, js.nextExit++); + + // Now our taken path. Bring the regs back, we didn't flush 'em after all. + SetJumpTarget(ptr); + RestoreState(state); + CONDITIONAL_LOG_EXIT(targetAddr); + + if (andLink) + gpr.SetImm(MIPS_REG_RA, js.compilerPC + 8); + + // Don't forget to run the delay slot if likely. + if (likely) + CompileDelaySlot(DELAYSLOT_NICE); + + // Account for the increment in the loop. + js.compilerPC = targetAddr - 4; + // In case the delay slot was a break or something. + js.compiling = true; + } + else + { + // Take the branch + if (andLink) + MOV(32, M(&mips_->r[MIPS_REG_RA]), Imm32(js.compilerPC + 8)); + CONDITIONAL_LOG_EXIT(targetAddr); + WriteExit(targetAddr, js.nextExit++); + + // Not taken + SetJumpTarget(ptr); + RestoreState(state); + CONDITIONAL_LOG_EXIT(notTakenAddr); + + // Account for the delay slot. + js.compilerPC += 4; + // In case the delay slot was a break or something. + js.compiling = true; + } + } + else + { + Gen::FixupBranch ptr; + if (!likely) + { + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE_FLUSH); + else + FlushAll(); + ptr = J_CC(cc, true); + } + else + { + FlushAll(); + ptr = J_CC(cc, true); + CompileDelaySlot(DELAYSLOT_FLUSH); + } + + // Take the branch + if (andLink) + MOV(32, M(&mips_->r[MIPS_REG_RA]), Imm32(js.compilerPC + 8)); + CONDITIONAL_LOG_EXIT(targetAddr); + WriteExit(targetAddr, js.nextExit++); + + // Not taken + SetJumpTarget(ptr); + CONDITIONAL_LOG_EXIT(notTakenAddr); + WriteExit(notTakenAddr, js.nextExit++); + js.compiling = false; + } +} + void Jit::BranchRSRTComp(MIPSOpcode op, Gen::CCFlags cc, bool likely) { CONDITIONAL_LOG; @@ -225,71 +325,7 @@ void Jit::BranchRSRTComp(MIPSOpcode op, Gen::CCFlags cc, bool likely) CMP(32, gpr.R(rs), gpr.R(rt)); } - // We may want to try to continue along this branch a little while, to reduce reg flushing. - bool predictTakeBranch = PredictTakeBranch(targetAddr, likely); - bool continueBranch = false; - // Likely delay slots may change regs, can't take those branches inline safely. - if (CanContinueBranch() && (!likely || !predictTakeBranch)) - { - continueBranch = true; - if (predictTakeBranch) - cc = FlipCCFlag(cc); - } - - Gen::FixupBranch ptr; - RegCacheState state; - if (!likely) - { - if (!delaySlotIsNice) - CompileDelaySlot(DELAYSLOT_SAFE_FLUSH, state); - else - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - } - else - { - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - CompileDelaySlot(DELAYSLOT_FLUSH); - } - - if (continueBranch && predictTakeBranch) - { - // We flipped the cc, the not taken case is first. - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - WriteExit(js.compilerPC + 8, js.nextExit++); - - // Now our taken path. - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - - // Take the branch - CONDITIONAL_LOG_EXIT(targetAddr); - WriteExit(targetAddr, js.nextExit++); - - // Not taken - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - - if (continueBranch && !predictTakeBranch) - { - // Account for the delay slot. - js.compilerPC += 4; - RestoreState(state); - // In case the delay slot was a break or something. - js.compiling = true; - } - else - { - WriteExit(js.compilerPC + 8, js.nextExit++); - js.compiling = false; - } + CompBranchExits(cc, targetAddr, js.compilerPC + 8, delaySlotIsNice, likely, false); } void Jit::BranchRSZeroComp(MIPSOpcode op, Gen::CCFlags cc, bool andLink, bool likely) @@ -347,75 +383,7 @@ void Jit::BranchRSZeroComp(MIPSOpcode op, Gen::CCFlags cc, bool andLink, bool li gpr.MapReg(rs, true, false); CMP(32, gpr.R(rs), Imm32(0)); - // We may want to try to continue along this branch a little while, to reduce reg flushing. - bool predictTakeBranch = PredictTakeBranch(targetAddr, likely); - bool continueBranch = false; - // Likely delay slots may change regs, can't take those branches inline safely. - if (CanContinueBranch() && (!likely || !predictTakeBranch)) - { - continueBranch = true; - if (predictTakeBranch) - cc = FlipCCFlag(cc); - } - - Gen::FixupBranch ptr; - RegCacheState state; - if (!likely) - { - if (!delaySlotIsNice) - CompileDelaySlot(DELAYSLOT_SAFE_FLUSH, state); - else - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - } - else - { - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - CompileDelaySlot(DELAYSLOT_FLUSH); - } - - if (continueBranch && predictTakeBranch) - { - // We flipped the cc, the not taken case is first. - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - WriteExit(js.compilerPC + 8, js.nextExit++); - - // Now our taken path. - SetJumpTarget(ptr); - if (andLink) - gpr.SetImm(MIPS_REG_RA, js.compilerPC + 8); - CONDITIONAL_LOG_EXIT(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - - // Take the branch - if (andLink) - MOV(32, M(&mips_->r[MIPS_REG_RA]), Imm32(js.compilerPC + 8)); - CONDITIONAL_LOG_EXIT(targetAddr); - WriteExit(targetAddr, js.nextExit++); - - // Not taken - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - - if (continueBranch && !predictTakeBranch) - { - // Account for the delay slot. - js.compilerPC += 4; - RestoreState(state); - // In case the delay slot was a break or something. - js.compiling = true; - } - else - { - WriteExit(js.compilerPC + 8, js.nextExit++); - js.compiling = false; - } + CompBranchExits(cc, targetAddr, js.compilerPC + 8, delaySlotIsNice, likely, andLink); } @@ -477,72 +445,9 @@ void Jit::BranchFPFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely) if (!likely && delaySlotIsNice) CompileDelaySlot(DELAYSLOT_NICE); - // We may want to try to continue along this branch a little while, to reduce reg flushing. - bool predictTakeBranch = PredictTakeBranch(targetAddr, likely); - bool continueBranch = false; - // Likely delay slots may change regs, can't take those branches inline safely. - if (CanContinueBranch() && (!likely || !predictTakeBranch)) - { - continueBranch = true; - if (predictTakeBranch) - cc = FlipCCFlag(cc); - } - TEST(32, M((void *)&(mips_->fpcond)), Imm32(1)); - Gen::FixupBranch ptr; - RegCacheState state; - if (!likely) - { - if (!delaySlotIsNice) - CompileDelaySlot(DELAYSLOT_SAFE_FLUSH, state); - else - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - } - else - { - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - CompileDelaySlot(DELAYSLOT_FLUSH); - } - if (continueBranch && predictTakeBranch) - { - // We flipped the cc, the not taken case is first. - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - WriteExit(js.compilerPC + 8, js.nextExit++); - - // Now our taken path. - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - - // Take the branch - CONDITIONAL_LOG_EXIT(targetAddr); - WriteExit(targetAddr, js.nextExit++); - - // Not taken - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(js.compilerPC + 8); - - if (continueBranch && !predictTakeBranch) - { - // Account for the delay slot. - js.compilerPC += 4; - RestoreState(state); - // In case the delay slot was a break or something. - js.compiling = true; - } - else - { - WriteExit(js.compilerPC + 8, js.nextExit++); - js.compiling = false; - } + CompBranchExits(cc, targetAddr, js.compilerPC + 8, delaySlotIsNice, likely, false); } @@ -584,81 +489,13 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely) if (delaySlotIsBranch && (signed short)(delaySlotOp & 0xFFFF) != (signed short)(op & 0xFFFF) - 1) ERROR_LOG_REPORT(JIT, "VFPU branch in VFPU delay slot at %08x with different target %d / %d", js.compilerPC, (signed short)(delaySlotOp & 0xFFFF), (signed short)(op & 0xFFFF) - 1); - // We may want to try to continue along this branch a little while, to reduce reg flushing. - bool predictTakeBranch = PredictTakeBranch(targetAddr, likely); - bool continueBranch = false; - // Likely delay slots may change regs, can't take those branches inline safely. - // TODO: Maybe delaySlotIsBranch could work, but let's play it safe. - if (CanContinueBranch() && (!likely || !predictTakeBranch) && !delaySlotIsBranch) - { - continueBranch = true; - if (predictTakeBranch) - cc = FlipCCFlag(cc); - } - // THE CONDITION int imm3 = (op >> 18) & 7; - //int val = (mips_->vfpuCtrl[VFPU_CTRL_CC] >> imm3) & 1; TEST(32, M((void *)&(mips_->vfpuCtrl[VFPU_CTRL_CC])), Imm32(1 << imm3)); - Gen::FixupBranch ptr; - RegCacheState state; - if (!likely) - { - if (!delaySlotIsNice && !delaySlotIsBranch) - CompileDelaySlot(DELAYSLOT_SAFE_FLUSH, state); - else - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - } - else - { - GetStateAndFlushAll(state); - ptr = J_CC(cc, true); - if (!delaySlotIsBranch) - CompileDelaySlot(DELAYSLOT_FLUSH); - } u32 notTakenTarget = js.compilerPC + (delaySlotIsBranch ? 4 : 8); - - if (continueBranch && predictTakeBranch) - { - // We flipped the cc, the not taken case is first. - CONDITIONAL_LOG_EXIT(notTakenTarget); - WriteExit(notTakenTarget, js.nextExit++); - - // Now our taken path. - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - - // Take the branch - CONDITIONAL_LOG_EXIT(targetAddr); - WriteExit(targetAddr, js.nextExit++); - - // Not taken - SetJumpTarget(ptr); - CONDITIONAL_LOG_EXIT(notTakenTarget); - - if (continueBranch && !predictTakeBranch) - { - // Account for the delay slot. - if (!delaySlotIsBranch) - js.compilerPC += 4; - RestoreState(state); - // In case the delay slot was a break or something. - js.compiling = true; - } - else - { - WriteExit(notTakenTarget, js.nextExit++); - js.compiling = false; - } + CompBranchExits(cc, targetAddr, notTakenTarget, delaySlotIsNice, likely, false); } @@ -749,18 +586,21 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } MIPSGPReg rs = _RS; MIPSGPReg rd = _RD; + bool andLink = (op & 0x3f) == 9; MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4); bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs); + if (andLink && rs == rd) + delaySlotIsNice = false; CONDITIONAL_NICE_DELAYSLOT; if (IsSyscall(delaySlotOp)) { - _dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported."); - // If this is a syscall, write the pc (for thread switching and other good reasons.) gpr.MapReg(rs, true, false); MOV(32, M(¤tMIPS->pc), gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_FLUSH); // Syscalls write the exit code for us. @@ -769,9 +609,11 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } else if (delaySlotIsNice) { + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { // According to the MIPS ABI, there are some regs we don't need to preserve. // Let's discard them so we don't need to write them back. // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash @@ -787,8 +629,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) { // Account for the increment in the loop. js.compilerPC = gpr.GetImm(rs) - 4; - if ((op & 0x3f) == 9) - gpr.SetImm(rd, js.compilerPC + 8); // In case the delay slot was a break or something. js.compiling = true; return; @@ -802,6 +642,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op) // Latch destination now - save it in memory. gpr.MapReg(rs, true, false); MOV(32, M(&savedPC), gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); MOV(32, R(EAX), M(&savedPC)); FlushAll(); @@ -812,7 +654,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) case 8: //jr break; case 9: //jalr - MOV(32, M(&mips_->r[rd]), Imm32(js.compilerPC + 8)); break; default: _dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled"); diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 4b26b5b47d..ded917e03a 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -64,6 +64,8 @@ static const float zero = 0.0f; const u32 MEMORY_ALIGNED16( noSignMask[4] ) = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; const u32 MEMORY_ALIGNED16( signBitLower[4] ) = {0x80000000, 0, 0, 0}; const float MEMORY_ALIGNED16( oneOneOneOne[4] ) = {1.0f, 1.0f, 1.0f, 1.0f}; +const u32 MEMORY_ALIGNED16( solidOnes[4] ) = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; +const u32 MEMORY_ALIGNED16( fourinfnan[4] ) = {0x7F800000, 0x7F800000, 0x7F800000, 0x7F800000}; void Jit::Comp_VPFX(MIPSOpcode op) { @@ -408,8 +410,6 @@ void Jit::Comp_SVQ(MIPSOpcode op) } break; - - default: DISABLE; break; @@ -722,6 +722,9 @@ void Jit::Comp_Vcmov(MIPSOpcode op) { SetJumpTarget(skip); } } + + ApplyPrefixD(dregs, sz); + fpr.ReleaseSpillLocks(); } @@ -881,13 +884,17 @@ void Jit::Comp_Vcmp(MIPSOpcode op) { // Some, we just fall back to the interpreter. switch (cond) { - case VC_EN: // c = my_isnan(s[i]); break; case VC_EI: // c = my_isinf(s[i]); break; - case VC_ES: // c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection - case VC_NN: // c = !my_isnan(s[i]); break; case VC_NI: // c = !my_isinf(s[i]); break; - case VC_NS: // c = !my_isnan(s[i]) && !my_isinf(s[i]); break; DISABLE; + break; + case VC_ES: // c = my_isnan(s[i]) || my_isinf(s[i]); break; // Tekken Dark Resurrection + case VC_NS: // c = !my_isnan(s[i]) && !my_isinf(s[i]); break; + case VC_EN: // c = my_isnan(s[i]); break; + case VC_NN: // c = !my_isnan(s[i]); break; + if (_VS != _VT) + DISABLE; + break; default: break; } @@ -916,7 +923,35 @@ void Jit::Comp_Vcmp(MIPSOpcode op) { bool compareToZero = false; int comparison = -1; bool flip = false; + bool inverse = false; + switch (cond) { + case VC_ES: + comparison = -1; // We will do the compare up here. XMM1 will have the bits. + MOVSS(XMM1, fpr.V(sregs[i])); + ANDPS(XMM1, M((void *)&fourinfnan)); + PCMPEQD(XMM1, M((void *)&fourinfnan)); // Integer comparison + break; + + case VC_NS: + comparison = -1; // We will do the compare up here. XMM1 will have the bits. + MOVSS(XMM1, fpr.V(sregs[i])); + ANDPS(XMM1, M((void *)&fourinfnan)); + PCMPEQD(XMM1, M((void *)&fourinfnan)); // Integer comparison + XORPS(XMM1, M((void *)&solidOnes)); + break; + + case VC_EN: + comparison = CMP_UNORD; + compareTwo = true; + break; + + case VC_NN: + comparison = CMP_UNORD; + compareTwo = true; + inverse = true; + break; + case VC_EQ: // c = s[i] == t[i]; break; comparison = CMP_EQ; compareTwo = true; @@ -963,17 +998,22 @@ void Jit::Comp_Vcmp(MIPSOpcode op) { DISABLE; } - if (compareTwo) { - if (!flip) { + if (comparison != -1) { + if (compareTwo) { + if (!flip) { + MOVSS(XMM1, fpr.V(sregs[i])); + CMPSS(XMM1, fpr.V(tregs[i]), comparison); + } else { + MOVSS(XMM1, fpr.V(tregs[i])); + CMPSS(XMM1, fpr.V(sregs[i]), comparison); + } + } else if (compareToZero) { MOVSS(XMM1, fpr.V(sregs[i])); - CMPSS(XMM1, fpr.V(tregs[i]), comparison); - } else { - MOVSS(XMM1, fpr.V(tregs[i])); - CMPSS(XMM1, fpr.V(sregs[i]), comparison); + CMPSS(XMM1, R(XMM0), comparison); + } + if (inverse) { + XORPS(XMM1, M((void *)&solidOnes)); } - } else if (compareToZero) { - MOVSS(XMM1, fpr.V(sregs[i])); - CMPSS(XMM1, R(XMM0), comparison); } MOVSS(M((void *) &ssCompareTemp), XMM1); @@ -1105,6 +1145,10 @@ void Jit::Comp_Vi2f(MIPSOpcode op) { // Translation of ryg's half_to_float5_SSE2 void Jit::Comp_Vh2f(MIPSOpcode op) { + CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) + DISABLE; + #define SSE_CONST4(name, val) static const u32 MEMORY_ALIGNED16(name[4]) = { (val), (val), (val), (val) } SSE_CONST4(mask_nosign, 0x7fff); @@ -1113,11 +1157,6 @@ void Jit::Comp_Vh2f(MIPSOpcode op) { SSE_CONST4(exp_infnan, 255 << 23); #undef SSE_CONST4 - - CONDITIONAL_DISABLE; - if (js.HasUnknownPrefix()) - DISABLE; - VectorSize sz = GetVecSize(op); VectorSize outsize; switch (sz) { @@ -1139,7 +1178,7 @@ void Jit::Comp_Vh2f(MIPSOpcode op) { X64Reg tempR = fpr.GetFreeXReg(); MOVSS(XMM0, fpr.V(sregs[0])); - if (sz != V_Single) { + if (sz != V_Single) { MOVSS(XMM1, fpr.V(sregs[1])); PUNPCKLDQ(XMM0, R(XMM1)); } @@ -1413,6 +1452,55 @@ void Jit::Comp_Vsgn(MIPSOpcode op) { fpr.ReleaseSpillLocks(); } +void Jit::Comp_Vocp(MIPSOpcode op) { + CONDITIONAL_DISABLE; + + if (js.HasUnknownPrefix()) + DISABLE; + + VectorSize sz = GetVecSize(op); + int n = GetNumVectorElements(sz); + + u8 sregs[4], dregs[4]; + GetVectorRegsPrefixS(sregs, sz, _VS); + GetVectorRegsPrefixD(dregs, sz, _VD); + + X64Reg tempxregs[4]; + for (int i = 0; i < n; ++i) + { + if (!IsOverlapSafeAllowS(dregs[i], i, n, sregs)) + { + int reg = fpr.GetTempV(); + fpr.MapRegV(reg, MAP_NOINIT | MAP_DIRTY); + fpr.SpillLockV(reg); + tempxregs[i] = fpr.VX(reg); + } + else + { + fpr.MapRegV(dregs[i], (dregs[i] == sregs[i] ? 0 : MAP_NOINIT) | MAP_DIRTY); + fpr.SpillLockV(dregs[i]); + tempxregs[i] = fpr.VX(dregs[i]); + } + } + + MOVSS(XMM1, M((void *)&one)); + for (int i = 0; i < n; ++i) + { + MOVSS(XMM0, R(XMM1)); + SUBSS(XMM0, fpr.V(sregs[i])); + MOVSS(tempxregs[i], R(XMM0)); + } + + for (int i = 0; i < n; ++i) { + if (!fpr.V(dregs[i]).IsSimpleReg(tempxregs[i])) + MOVSS(fpr.V(dregs[i]), tempxregs[i]); + } + + ApplyPrefixD(dregs, sz); + + fpr.ReleaseSpillLocks(); +} + void Jit::Comp_VV2Op(MIPSOpcode op) { CONDITIONAL_DISABLE; @@ -1926,6 +2014,14 @@ void Jit::Comp_Vi2x(MIPSOpcode op) { void Jit::Comp_Vhoriz(MIPSOpcode op) { DISABLE; + + // Do any games use these a noticable amount? + switch ((op >> 16) & 31) { + case 6: // vfad + break; + case 7: // vavg + break; + } } void Jit::Comp_Viim(MIPSOpcode op) { @@ -2062,5 +2158,4 @@ void Jit::Comp_VRot(MIPSOpcode op) { fpr.ReleaseSpillLocks(); } - } diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index e1f5ac2f2a..b81503869d 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -243,13 +243,6 @@ void Jit::CompileDelaySlot(int flags, RegCacheState *state) LOAD_FLAGS; // restore flag! } -void Jit::CompileAt(u32 addr) -{ - CheckJitBreakpoint(addr, 0); - MIPSOpcode op = Memory::Read_Instruction(addr); - MIPSCompileOp(op); -} - void Jit::EatInstruction(MIPSOpcode op) { MIPSInfo info = MIPSGetInfo(op); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index b84a6fe0be..c4a80ec764 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -58,7 +58,8 @@ class Jit : public Gen::XCodeBlock { public: Jit(MIPSState *mips); - ~Jit(); + virtual ~Jit(); + void DoState(PointerWrap &p); static void DoDummyState(PointerWrap &p); @@ -72,7 +73,10 @@ public: void Compile(u32 em_address); // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); - void CompileAt(u32 addr); + bool IsInDispatch(const u8 *p) { + return asm_.IsInSpace(p); + } + void Comp_RunBlock(MIPSOpcode op); // Ops @@ -136,6 +140,7 @@ public: void Comp_Vfim(MIPSOpcode op); void Comp_VCrossQuat(MIPSOpcode op); void Comp_Vsgn(MIPSOpcode op); + void Comp_Vocp(MIPSOpcode op); void Comp_DoNothing(MIPSOpcode op); @@ -196,6 +201,7 @@ private: void CompITypeMemWrite(MIPSOpcode op, u32 bits, void *safeFunc); void CompITypeMemUnpairedLR(MIPSOpcode op, bool isStore); void CompITypeMemUnpairedLRInner(MIPSOpcode op, X64Reg shiftReg); + void CompBranchExits(CCFlags cc, u32 targetAddr, u32 notTakenAddr, bool delaySlotIsNice, bool likely, bool andLink); void CompFPTriArith(MIPSOpcode op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters); void CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN = false); diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index 1913f16507..b628b87fea 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -32,8 +32,10 @@ FPURegCache::FPURegCache() : mips(0), initialReady(false), emit(0) { void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) { this->mips = mips; - if (!initialReady) + if (!initialReady) { SetupInitialRegs(); + initialReady = true; + } memcpy(xregs, xregsInitial, sizeof(xregs)); memcpy(regs, regsInitial, sizeof(regs)); @@ -50,12 +52,14 @@ void FPURegCache::SetupInitialRegs() { regsInitial[i].location = base; base.IncreaseOffset(sizeof(float)); } - base = GetDefaultLocation(32); - for (int i = 32; i < NUM_MIPS_FPRS; i++) { + for (int i = 32; i < 32 + 128; i++) { + regsInitial[i].location = GetDefaultLocation(i); + } + base = GetDefaultLocation(32 + 128); + for (int i = 32 + 128; i < NUM_MIPS_FPRS; i++) { regsInitial[i].location = base; base.IncreaseOffset(sizeof(float)); } - initialReady = true; } void FPURegCache::SpillLock(int p1, int p2, int p3, int p4) { @@ -65,16 +69,16 @@ void FPURegCache::SpillLock(int p1, int p2, int p3, int p4) { if (p4 != 0xFF) regs[p4].locked = true; } -void FPURegCache::SpillLockV(const u8 *v, VectorSize sz) { +void FPURegCache::SpillLockV(const u8 *vec, VectorSize sz) { for (int i = 0; i < GetNumVectorElements(sz); i++) { - vregs[v[i]].locked = true; + vregs[vec[i]].locked = true; } } void FPURegCache::SpillLockV(int vec, VectorSize sz) { - u8 v[4]; - GetVectorRegs(v, sz, vec); - SpillLockV(v, sz); + u8 r[4]; + GetVectorRegs(r, sz, vec); + SpillLockV(r, sz); } void FPURegCache::MapRegV(int vreg, int flags) { @@ -82,18 +86,18 @@ void FPURegCache::MapRegV(int vreg, int flags) { } void FPURegCache::MapRegsV(int vec, VectorSize sz, int flags) { - u8 v[4]; - GetVectorRegs(v, sz, vec); - SpillLockV(v, sz); + u8 r[4]; + GetVectorRegs(r, sz, vec); + SpillLockV(r, sz); for (int i = 0; i < GetNumVectorElements(sz); i++) { - MapReg(v[i] + 32, (flags & MAP_NOINIT) == 0, (flags & MAP_DIRTY) != 0); + MapReg(r[i] + 32, (flags & MAP_NOINIT) == 0, (flags & MAP_DIRTY) != 0); } } -void FPURegCache::MapRegsV(const u8 *v, VectorSize sz, int flags) { - SpillLockV(v, sz); +void FPURegCache::MapRegsV(const u8 *r, VectorSize sz, int flags) { + SpillLockV(r, sz); for (int i = 0; i < GetNumVectorElements(sz); i++) { - MapReg(v[i] + 32, (flags & MAP_NOINIT) == 0, (flags & MAP_DIRTY) != 0); + MapReg(r[i] + 32, (flags & MAP_NOINIT) == 0, (flags & MAP_DIRTY) != 0); } } @@ -205,7 +209,7 @@ OpArg FPURegCache::GetDefaultLocation(int reg) const { if (reg < 32) { return M(&mips->f[reg]); } else if (reg < 32 + 128) { - return M(&mips->v[reg - 32]); + return M(&mips->v[voffset[reg - 32]]); } else { return M(&tempValues[reg - 32 - 128]); } @@ -264,9 +268,9 @@ X64Reg FPURegCache::GetFreeXReg() { } void FPURegCache::FlushX(X64Reg reg) { - if (reg >= NUM_X_FPREGS) + if (reg >= NUM_X_FPREGS) { PanicAlert("Flushing non existent reg"); - else if (xregs[reg].mipsReg != -1) { + } else if (xregs[reg].mipsReg != -1) { StoreFromRegister(xregs[reg].mipsReg); } } diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index adbaaa4f5d..a194aa5a92 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -22,6 +22,8 @@ #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/MIPSVFPUUtils.h" +#undef MAP_NOINIT + using namespace Gen; // GPRs are numbered 0 to 31 @@ -152,6 +154,7 @@ public: void FlushX(X64Reg reg); X64Reg GetFreeXReg(); + private: const int *GetAllocationOrder(int &count); void SetupInitialRegs(); diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 541bd6b885..7222504465 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -15,6 +15,8 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include + #include "Common.h" #include "MemoryUtil.h" #include "MemArena.h" @@ -26,7 +28,9 @@ #include "MIPS/JitCommon/JitCommon.h" #include "HLE/HLE.h" #include "CPU.h" -#include "Debugger/SymbolMap.h" +#include "Core/Debugger/SymbolMap.h" +#include "Core/Debugger/Breakpoints.h" +#include "Core/Config.h" namespace Memory { @@ -41,6 +45,8 @@ MemArena g_arena; // 64-bit: Pointers to low-mem (sub-0x10000000) mirror // 32-bit: Same as the corresponding physical/virtual pointers. u8 *m_pRAM; +u8 *m_pRAM2; +u8 *m_pRAM3; u8 *m_pScratchPad; u8 *m_pVRAM; @@ -51,6 +57,12 @@ u8 *m_pUncachedScratchPad; u8 *m_pPhysicalRAM; u8 *m_pUncachedRAM; u8 *m_pKernelRAM; // RAM mirrored up to "kernel space". Fully accessible at all times currently. +u8 *m_pPhysicalRAM2; +u8 *m_pUncachedRAM2; +u8 *m_pKernelRAM2; +u8 *m_pPhysicalRAM3; +u8 *m_pUncachedRAM3; +u8 *m_pKernelRAM3; u8 *m_pPhysicalVRAM; u8 *m_pUncachedVRAM; @@ -60,6 +72,8 @@ u8 *m_pUncachedVRAM; // These replace RAM_NORMAL_SIZE and RAM_NORMAL_MASK, respectively. u32 g_MemorySize; u32 g_MemoryMask; +// Used to store the PSP model on game startup. +u32 g_PSPModel; // We don't declare the IO region in here since its handled by other means. static MemoryView views[] = @@ -71,6 +85,14 @@ static MemoryView views[] = {&m_pRAM, &m_pPhysicalRAM, 0x08000000, g_MemorySize, MV_IS_PRIMARY_RAM}, // only from 0x08800000 is it usable (last 24 megs) {NULL, &m_pUncachedRAM, 0x48000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM}, {NULL, &m_pKernelRAM, 0x88000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM}, + // Starts at memory + 31 MB. + {&m_pRAM2, &m_pPhysicalRAM2, 0x09F00000, g_MemorySize, MV_IS_EXTRA1_RAM}, + {NULL, &m_pUncachedRAM2, 0x49F00000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_EXTRA1_RAM}, + {NULL, &m_pKernelRAM2, 0x89F00000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_EXTRA1_RAM}, + // Starts at memory + 31 * 2 MB. + {&m_pRAM3, &m_pPhysicalRAM3, 0x0BE00000, g_MemorySize, MV_IS_EXTRA2_RAM}, + {NULL, &m_pUncachedRAM3, 0x4BE00000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_EXTRA2_RAM}, + {NULL, &m_pKernelRAM3, 0x8BE00000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_EXTRA2_RAM}, // TODO: There are a few swizzled mirrors of VRAM, not sure about the best way to // implement those. @@ -86,9 +108,16 @@ void Init() // Using (Memory::g_MemorySize - 1) won't work for e.g. 0x04C00000. Memory::g_MemoryMask = 0x07FFFFFF; + // On some 32 bit platforms, you can only map < 32 megs at a time. + const static int MAX_MMAP_SIZE = 31 * 1024 * 1024; + _dbg_assert_msg_(MEMMAP, g_MemorySize < MAX_MMAP_SIZE * 3, "ACK - too much memory for three mmap views."); for (size_t i = 0; i < ARRAY_SIZE(views); i++) { if (views[i].flags & MV_IS_PRIMARY_RAM) - views[i].size = g_MemorySize; + views[i].size = std::min((int)g_MemorySize, MAX_MMAP_SIZE); + if (views[i].flags & MV_IS_EXTRA1_RAM) + views[i].size = std::min(std::max((int)g_MemorySize - MAX_MMAP_SIZE, 0), MAX_MMAP_SIZE); + if (views[i].flags & MV_IS_EXTRA2_RAM) + views[i].size = std::min(std::max((int)g_MemorySize - MAX_MMAP_SIZE * 2, 0), MAX_MMAP_SIZE); } base = MemoryMap_Setup(views, num_views, flags, &g_arena); @@ -98,12 +127,24 @@ void Init() void DoState(PointerWrap &p) { - auto s = p.Section("Memory", 1); + auto s = p.Section("Memory", 1, 2); if (!s) return; - p.DoArray(m_pRAM, g_MemorySize); + if (s < 2) { + if (!g_RemasterMode) + g_MemorySize = RAM_NORMAL_SIZE; + g_PSPModel = PSP_MODEL_FAT; + } else { + p.Do(g_PSPModel); + p.DoMarker("PSPModel"); + if (!g_RemasterMode) + g_MemorySize = g_PSPModel == PSP_MODEL_FAT ? RAM_NORMAL_SIZE : RAM_DOUBLE_SIZE; + } + + p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize); p.DoMarker("RAM"); + p.DoArray(m_pVRAM, VRAM_SIZE); p.DoMarker("VRAM"); p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE); @@ -116,13 +157,13 @@ void Shutdown() MemoryMap_Shutdown(views, num_views, flags, &g_arena); g_arena.ReleaseSpace(); base = NULL; - INFO_LOG(MEMMAP, "Memory system shut down."); + DEBUG_LOG(MEMMAP, "Memory system shut down."); } void Clear() { if (m_pRAM) - memset(m_pRAM, 0, g_MemorySize); + memset(GetPointerUnchecked(PSP_GetKernelMemoryBase()), 0, g_MemorySize); if (m_pScratchPad) memset(m_pScratchPad, 0, SCRATCHPAD_SIZE); if (m_pVRAM) @@ -135,7 +176,7 @@ Opcode Read_Instruction(u32 address) if (MIPS_IS_EMUHACK(inst) && MIPSComp::jit) { JitBlockCache *bc = MIPSComp::jit->GetBlockCache(); - int block_num = bc->GetBlockNumberFromEmuHackOp(inst); + int block_num = bc->GetBlockNumberFromEmuHackOp(inst, true); if (block_num >= 0) { return bc->GetOriginalFirstOp(block_num); } else { @@ -170,6 +211,9 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength) for (size_t i = 0; i < _iLength; i++) Write_U8(_iValue, (u32)(_Address + i)); } +#ifndef USING_GLES2 + CBreakPoints::ExecMemCheck(_Address, true, _iLength, currentMIPS->pc); +#endif } void GetString(std::string& _string, const u32 em_address) diff --git a/Core/MemMap.h b/Core/MemMap.h index 3fd45ddf54..9ae6488315 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -60,7 +60,10 @@ extern u8 *base; // These are guaranteed to point to "low memory" addresses (sub-32-bit). // 64-bit: Pointers to low-mem (sub-0x10000000) mirror // 32-bit: Same as the corresponding physical/virtual pointers. +// Broken into three chunks to workaround 32-bit mmap() limits. extern u8 *m_pRAM; +extern u8 *m_pRAM2; +extern u8 *m_pRAM3; extern u8 *m_pScratchPad; extern u8 *m_pVRAM; @@ -75,6 +78,7 @@ extern u8 *m_pUncachedVRAM; // These replace RAM_NORMAL_SIZE and RAM_NORMAL_MASK, respectively. extern u32 g_MemorySize; extern u32 g_MemoryMask; +extern u32 g_PSPModel; enum { @@ -82,6 +86,9 @@ enum RAM_NORMAL_SIZE = 0x02000000, RAM_NORMAL_MASK = RAM_NORMAL_SIZE - 1, + // Used if the PSP model is PSP-2000 (Slim). + RAM_DOUBLE_SIZE = RAM_NORMAL_SIZE * 2, + VRAM_SIZE = 0x200000, VRAM_MASK = VRAM_SIZE - 1, @@ -241,7 +248,6 @@ inline void Write_Float(float f, u32 address) // Reads a zero-terminated string from memory at the address. void GetString(std::string& _string, const u32 _Address); u8* GetPointer(const u32 address); -bool IsValidAddress(const u32 address); bool IsRAMAddress(const u32 address); bool IsVRAMAddress(const u32 address); @@ -274,6 +280,23 @@ inline void MemcpyUnchecked(void *to_data, const u32 from_address, const u32 len memcpy(to_data, GetPointerUnchecked(from_address), len); } +inline bool IsValidAddress(const u32 address) { + if ((address & 0x3E000000) == 0x08000000) { + return true; + } + else if ((address & 0x3F800000) == 0x04000000) { + return true; + } + else if ((address & 0xBFFF0000) == 0x00010000) { + return true; + } + else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + return true; + } + else + return false; +} + template void ReadStruct(u32 address, T *ptr) diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index c8f1ec7089..c8fa0b6a4a 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -40,7 +40,7 @@ namespace Memory u8 *GetPointer(const u32 address) { if ((address & 0x3E000000) == 0x08000000) { - return m_pRAM + (address & RAM_NORMAL_MASK); + return GetPointerUnchecked(address); } else if ((address & 0x3F800000) == 0x04000000) { return m_pVRAM + (address & VRAM_MASK); @@ -49,7 +49,7 @@ u8 *GetPointer(const u32 address) return m_pScratchPad + (address & SCRATCHPAD_MASK); } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { - return m_pRAM + (address & g_MemoryMask); + return GetPointerUnchecked(address); } else { ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); @@ -75,7 +75,7 @@ inline void ReadFromHardware(T &var, const u32 address) // Could just do a base-relative read, too.... TODO if ((address & 0x3E000000) == 0x08000000) { - var = *((const T*)&m_pRAM[address & RAM_NORMAL_MASK]); + var = *((const T*)GetPointerUnchecked(address)); } else if ((address & 0x3F800000) == 0x04000000) { var = *((const T*)&m_pVRAM[address & VRAM_MASK]); @@ -85,7 +85,7 @@ inline void ReadFromHardware(T &var, const u32 address) var = *((const T*)&m_pScratchPad[address & SCRATCHPAD_MASK]); } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { - var = *((const T*)&m_pRAM[address & g_MemoryMask]); + var = *((const T*)GetPointerUnchecked(address)); } else { @@ -113,7 +113,7 @@ inline void WriteToHardware(u32 address, const T data) // Could just do a base-relative write, too.... TODO if ((address & 0x3E000000) == 0x08000000) { - *(T*)&m_pRAM[address & RAM_NORMAL_MASK] = data; + *(T*)GetPointerUnchecked(address) = data; } else if ((address & 0x3F800000) == 0x04000000) { *(T*)&m_pVRAM[address & VRAM_MASK] = data; @@ -122,7 +122,7 @@ inline void WriteToHardware(u32 address, const T data) *(T*)&m_pScratchPad[address & SCRATCHPAD_MASK] = data; } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { - *(T*)&m_pRAM[address & g_MemoryMask] = data; + *(T*)GetPointerUnchecked(address) = data; } else { @@ -145,23 +145,6 @@ inline void WriteToHardware(u32 address, const T data) // ===================== -bool IsValidAddress(const u32 address) { - if ((address & 0x3E000000) == 0x08000000) { - return true; - } - else if ((address & 0x3F800000) == 0x04000000) { - return true; - } - else if ((address & 0xBFFF0000) == 0x00010000) { - return true; - } - else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { - return true; - } - else - return false; -} - bool IsRAMAddress(const u32 address) { if ((address & 0x3E000000) == 0x08000000) { return true; diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 15a0d86bd3..825d1e20a6 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -41,6 +41,7 @@ #include "HLE/sceKernelModule.h" #include "HLE/sceKernelMemory.h" #include "ELF/ParamSFO.h" +#include "Core/Config.h" // We gather the game info before actually loading/booting the ISO // to determine if the emulator should enable extra memory and @@ -72,6 +73,7 @@ void InitMemoryForGameISO(std::string fileToStart) { pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); + std::string gameID; std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); @@ -79,11 +81,9 @@ void InitMemoryForGameISO(std::string fileToStart) { if (fileInfo.exists) { - u8 *paramsfo = new u8[(size_t)fileInfo.size]; - u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ); - pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); - pspFileSystem.CloseFile(fd); - if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) + std::vector paramsfo; + pspFileSystem.ReadEntireFile(sfoPath, paramsfo); + if (g_paramSFO.ReadSFO(paramsfo)) { gameID = g_paramSFO.GetValueString("DISC_ID"); @@ -98,7 +98,6 @@ void InitMemoryForGameISO(std::string fileToStart) { } DEBUG_LOG(LOADER, "HDRemaster mode is %s", g_RemasterMode? "true": "false"); } - delete [] paramsfo; } } @@ -110,18 +109,15 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string) PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); if (fileInfo.exists) { - u8 *paramsfo = new u8[(size_t)fileInfo.size]; - u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ); - pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); - pspFileSystem.CloseFile(fd); - if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) + std::vector paramsfo; + pspFileSystem.ReadEntireFile(sfoPath, paramsfo); + if (g_paramSFO.ReadSFO(paramsfo)) { char title[1024]; sprintf(title, "%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("TITLE").c_str()); INFO_LOG(LOADER, "%s", title); host->SetWindowTitle(title); } - delete [] paramsfo; } diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 8af3a5bc0e..615a4875ad 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -65,6 +65,19 @@ namespace SaveState void *cbUserData; }; + CChunkFileReader::Error SaveToRam(std::vector &data) { + SaveStart state; + size_t sz = CChunkFileReader::MeasurePtr(state); + if (data.size() < sz) + data.resize(sz); + return CChunkFileReader::SavePtr(&data[0], state); + } + + CChunkFileReader::Error LoadFromRam(std::vector &data) { + SaveStart state; + return CChunkFileReader::LoadPtr(&data[0], state); + } + struct StateRingbuffer { StateRingbuffer(int size) : first_(0), next_(0), size_(size) @@ -78,12 +91,7 @@ namespace SaveState if ((next_ % size_) == first_) ++first_; - SaveStart state; - size_t sz = CChunkFileReader::MeasurePtr(state); - if (states_[n].size() < sz) - states_[n].resize(sz); - - return CChunkFileReader::SavePtr(&states_[n][0], state); + return SaveToRam(states_[n]); } CChunkFileReader::Error Restore() @@ -96,8 +104,7 @@ namespace SaveState if (states_[n].empty()) return CChunkFileReader::ERROR_BAD_FILE; - SaveStart state; - return CChunkFileReader::LoadPtr(&states_[n][0], state); + return LoadFromRam(states_[n]); } void Clear() @@ -193,17 +200,18 @@ namespace SaveState return !rewindStates.Empty(); } - + static const char *STATE_EXTENSION = "ppst"; + static const char *SCREENSHOT_EXTENSION = "jpg"; // Slot utilities - std::string GenerateSaveSlotFilename(int slot) + std::string GenerateSaveSlotFilename(int slot, const char *extension) { char discID[256]; char temp[256]; sprintf(discID, "%s_%s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("DISC_VERSION").c_str()); - sprintf(temp, "ms0:/PSP/PPSSPP_STATE/%s_%i.ppst", discID, slot); + sprintf(temp, "ms0:/PSP/PPSSPP_STATE/%s_%i.%s", discID, slot, extension); std::string hostPath; if (pspFileSystem.GetHostPath(std::string(temp), hostPath)) { return hostPath; @@ -214,7 +222,7 @@ namespace SaveState void LoadSlot(int slot, Callback callback, void *cbUserData) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); if (!fn.empty()) { Load(fn, callback, cbUserData); } else { @@ -227,7 +235,7 @@ namespace SaveState void SaveSlot(int slot, Callback callback, void *cbUserData) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); if (!fn.empty()) { Save(fn, callback, cbUserData); } else { @@ -240,7 +248,13 @@ namespace SaveState bool HasSaveInSlot(int slot) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); + return File::Exists(fn); + } + + bool HasScreenshotInSlot(int slot) + { + std::string fn = GenerateSaveSlotFilename(slot, SCREENSHOT_EXTENSION); return File::Exists(fn); } @@ -264,7 +278,7 @@ namespace SaveState int newestSlot = -1; tm newestDate = {0}; for (int i = 0; i < SAVESTATESLOTS; i++) { - std::string fn = GenerateSaveSlotFilename(i); + std::string fn = GenerateSaveSlotFilename(i, STATE_EXTENSION); if (File::Exists(fn)) { tm time = File::GetModifTime(fn); if (newestDate < time) { @@ -326,13 +340,16 @@ namespace SaveState return; rewindLastTime = time_now(); + DEBUG_LOG(BOOT, "saving rewind state"); rewindStates.Save(); } void Process() { +#ifndef USING_GLES2 if (g_Config.iRewindFlipFrequency != 0 && gpuStats.numFlips != 0) CheckRewindState(); +#endif if (!needsProcess) return; diff --git a/Core/SaveState.h b/Core/SaveState.h index 65eccdb9ae..088600b904 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -17,7 +17,7 @@ #include -class PointerWrap; +#include "ChunkFile.h" namespace SaveState { @@ -33,9 +33,12 @@ namespace SaveState void LoadSlot(int slot, Callback callback, void *cbUserData = 0); // Checks whether there's an existing save in the specified slot. bool HasSaveInSlot(int slot); + bool HasScreenshotInSlot(int slot); // Returns -1 if there's no newest slot. int GetNewestSlot(); + std::string GenerateSaveSlotFilename(int slot, const char *extension); + // Load the specified file into the current state (async.) // Warning: callback will be called on a different thread. void Load(const std::string &filename, Callback callback = 0, void *cbUserData = 0); @@ -44,6 +47,9 @@ namespace SaveState // Warning: callback will be called on a different thread. void Save(const std::string &filename, Callback callback = 0, void *cbUserData = 0); + CChunkFileReader::Error SaveToRam(std::vector &state); + CChunkFileReader::Error LoadFromRam(std::vector &state); + // For testing / automated tests. Runs a save state verification pass (async.) // Warning: callback will be called on a different thread. void Verify(Callback callback = 0, void *cbUserData = 0); diff --git a/Core/System.cpp b/Core/System.cpp index 6c044bf5ce..161af350ca 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -153,9 +153,14 @@ void CPU_Init() { // Default memory settings // Seems to be the safest place currently.. - Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE; // 32 MB of ram by default + if (g_Config.iPSPModel == PSP_MODEL_FAT) + Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE; // 32 MB of ram by default + else + Memory::g_MemorySize = Memory::RAM_DOUBLE_SIZE; + g_RemasterMode = false; g_DoubleTextureCoordinates = false; + Memory::g_PSPModel = g_Config.iPSPModel; std::string filename = coreParameter.fileToStart; IdentifiedFileType type = Identify_File(filename); @@ -392,17 +397,17 @@ void InitSysDirectories() { if (!g_Config.memCardDirectory.empty() && !g_Config.flash0Directory.empty()) return; - const std::string path = ConvertWStringToUTF8(File::GetExeDirectory()); + const std::string path = File::GetExeDirectory(); // Mount a filesystem - g_Config.flash0Directory = path + "/flash0/"; + g_Config.flash0Directory = path + "flash0/"; // Detect the "My Documents"(XP) or "Documents"(on Vista/7/8) folder. wchar_t myDocumentsPath[MAX_PATH]; const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/"; - const std::string installedFile = path + "/installed.txt"; + const std::string installedFile = path + "installed.txt"; const bool installed = File::Exists(installedFile); // If installed.txt exists(and we can determine the Documents directory) @@ -430,7 +435,7 @@ void InitSysDirectories() { if (lastSlash != (g_Config.memCardDirectory.length() - 1)) g_Config.memCardDirectory.append("/"); } else { - g_Config.memCardDirectory = path + "/memstick/"; + g_Config.memCardDirectory = path + "memstick/"; } // Create the memstickpath before trying to write to it, and fall back on Documents yet again diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index 19b19e0c1d..fe94982977 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -382,6 +382,7 @@ void BlockAllocator::ListBlocks() const const Block &b = *bp; INFO_LOG(HLE, "Block: %08x - %08x size %08x taken=%i tag=%s", b.start, b.start+b.size, b.size, b.taken ? 1:0, b.tag); } + INFO_LOG(HLE,"-----------"); } u32 BlockAllocator::GetLargestFreeBlockSize() const diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp new file mode 100644 index 0000000000..0976e25a1d --- /dev/null +++ b/Core/Util/GameManager.cpp @@ -0,0 +1,309 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "file/file_util.h" +#include "ext/libzip/zip.h" +#include "thread/thread.h" +#include "util/text/utf8.h" + +#include "Common/Log.h" +#include "Common/FileUtil.h" +#include "Core/Config.h" +#include "Core/System.h" +#include "Core/Util/GameManager.h" + +GameManager g_GameManager; + +GameManager::GameManager() + : installInProgress_(false), installProgress_(0.0f) { +} + +std::string GameManager::GetTempFilename() const { +#ifdef _WIN32 + wchar_t tempPath[MAX_PATH]; + GetTempPath(MAX_PATH, tempPath); + wchar_t buffer[MAX_PATH]; + GetTempFileName(tempPath, L"PSP", 1, buffer); + return ConvertWStringToUTF8(buffer); +#else + return g_Config.externalDirectory + "/ppsspp.dl"; +#endif +} + +bool GameManager::IsGameInstalled(std::string name) { + std::string pspGame = GetSysDirectory(DIRECTORY_GAME); + return File::Exists(pspGame + name); +} + +bool GameManager::DownloadAndInstall(std::string storeZipUrl) { + if (curDownload_.get() != 0) { + ERROR_LOG(HLE, "Can only process one download at a time"); + return false; + } + if (installInProgress_) { + ERROR_LOG(HLE, "Can't download when an install is in progress (yet)"); + return false; + } + + std::string filename = GetTempFilename(); + curDownload_ = g_DownloadManager.StartDownload(storeZipUrl, filename); + return true; +} + +bool GameManager::Uninstall(std::string name) { + if (name.empty()) { + ERROR_LOG(HLE, "Cannot remove an empty-named game"); + return false; + } + std::string gameDir = GetSysDirectory(DIRECTORY_GAME) + name; + INFO_LOG(HLE, "Deleting %s", gameDir.c_str()); + if (!File::Exists(gameDir)) { + ERROR_LOG(HLE, "Game %s not installed, cannot uninstall", name.c_str()); + return false; + } + + bool success = File::DeleteDirRecursively(gameDir); + if (success) { + INFO_LOG(HLE, "Successfully deleted game %s", name.c_str()); + g_Config.CleanRecent(); + return true; + } else { + ERROR_LOG(HLE, "Failed to delete game %s", name.c_str()); + return false; + } +} + +void GameManager::Update() { + if (curDownload_.get() && curDownload_->Done()) { + INFO_LOG(HLE, "Download completed! Status = %i", curDownload_->ResultCode()); + std::string zipName = curDownload_->outfile(); + if (curDownload_->ResultCode() == 200) { + if (!File::Exists(zipName)) { + ERROR_LOG(HLE, "Downloaded file %s does not exist :(", zipName.c_str()); + curDownload_.reset(); + return; + } + // Install the game! + InstallGame(zipName); + // Doesn't matter if the install succeeds or not, we delete the temp file to not squander space. + // TODO: Handle disk full? + deleteFile(zipName.c_str()); + } else { + ERROR_LOG(HLE, "Expected HTTP status code 200, got status code %i. Install cancelled.", curDownload_->ResultCode()); + deleteFile(zipName.c_str()); + } + curDownload_.reset(); + } +} + +bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { + if (installInProgress_) { + ERROR_LOG(HLE, "Cannot have two installs in progress at the same time"); + return false; + } + + installInProgress_ = true; + + std::string pspGame = GetSysDirectory(DIRECTORY_GAME); + INFO_LOG(HLE, "Installing %s into %s", zipfile.c_str(), pspGame.c_str()); + + if (!File::Exists(zipfile)) { + ERROR_LOG(HLE, "ZIP file %s doesn't exist", zipfile.c_str()); + return false; + } + + int error; +#ifdef _WIN32 + struct zip *z = zip_open(ConvertUTF8ToWString(zipfile).c_str(), 0, &error); +#elif defined(__SYMBIAN32__) + // If zipfile is non-ascii, this may not function correctly. Other options? + struct zip *z = zip_open(std::wstring(zipfile.begin(), zipfile.end()).c_str(), 0, &error); +#else + struct zip *z = zip_open(zipfile.c_str(), 0, &error); +#endif + if (!z) { + ERROR_LOG(HLE, "Failed to open ZIP file %s, error code=%i", zipfile.c_str(), error); + return false; + } + + int numFiles = zip_get_num_files(z); + + // First, find all the directories, and precreate them before we fill in with files. + // Also, verify that this is a PSP zip file with the correct layout. + bool isPSP = false; + int stripChars = 0; + + for (int i = 0; i < numFiles; i++) { + const char *fn = zip_get_name(z, i, 0); + std::string zippedName = fn; + if (zippedName.find("EBOOT.PBP") != std::string::npos) { + int slashCount = 0; + int lastSlashLocation = -1; + int slashLocation = -1; + for (size_t i = 0; i < zippedName.size(); i++) { + if (zippedName[i] == '/') { + slashCount++; + slashLocation = lastSlashLocation; + lastSlashLocation = (int)i; + } + } + if (slashCount >= 1 && (!isPSP || slashLocation < stripChars + 1)) { + stripChars = slashLocation + 1; + isPSP = true; + } else { + INFO_LOG(HLE, "Wrong number of slashes (%i) in %s", slashCount, zippedName.c_str()); + } + } + } + + if (!isPSP) { + ERROR_LOG(HLE, "File not a PSP game, no EBOOT.PBP found."); + installProgress_ = 0.0f; + installInProgress_ = false; + installError_ = "Not a PSP game"; + InstallDone(); + return false; + } + + size_t allBytes = 0, bytesCopied = 0; + + // Create all the directories in one pass + std::set createdDirs; + for (int i = 0; i < numFiles; i++) { + const char *fn = zip_get_name(z, i, 0); + std::string zippedName = fn; + std::string outFilename = pspGame + zippedName.substr(stripChars); + bool isDir = *outFilename.rbegin() == '/'; + if (!isDir && outFilename.find("/") != std::string::npos) { + outFilename = outFilename.substr(0, outFilename.rfind('/')); + } + if (createdDirs.find(outFilename) == createdDirs.end()) { + File::CreateFullPath(outFilename.c_str()); + createdDirs.insert(outFilename); + } + if (!isDir && strstr(fn, "/") != 0) { + struct zip_stat zstat; + if (zip_stat_index(z, i, 0, &zstat) >= 0) { + allBytes += zstat.size; + } + } + } + + // Now, loop through again in a second pass, writing files. + std::vector createdFiles; + for (int i = 0; i < numFiles; i++) { + const char *fn = zip_get_name(z, i, 0); + // Note that we do NOT write files that are not in a directory, to avoid random + // README files etc. + if (strstr(fn, "/") != 0) { + struct zip_stat zstat; + zip_stat_index(z, i, 0, &zstat); + size_t size = zstat.size; + + fn += stripChars; + + std::string outFilename = pspGame + fn; + bool isDir = *outFilename.rbegin() == '/'; + if (isDir) + continue; + + if (i < 10) { + INFO_LOG(HLE, "Writing %i bytes to %s", (int)size, outFilename.c_str()); + } + + zip_file *zf = zip_fopen_index(z, i, 0); + FILE *f = fopen(outFilename.c_str(), "wb"); + if (f) { + size_t pos = 0; + const size_t blockSize = 1024 * 128; + u8 *buffer = new u8[blockSize]; + while (pos < size) { + size_t bs = std::min(blockSize, pos - size); + zip_fread(zf, buffer, bs); + size_t written = fwrite(buffer, 1, bs, f); + if (written != bs) { + ERROR_LOG(HLE, "Wrote %i bytes out of %i - Disk full?", (int)written, (int)bs); + delete [] buffer; + buffer = 0; + fclose(f); + zip_fclose(zf); + deleteFile(outFilename.c_str()); + // Yes it's a goto. Sue me. I think it's appropriate here. + goto bail; + } + pos += bs; + + bytesCopied += bs; + installProgress_ = (float)bytesCopied / (float)allBytes; + // printf("Progress: %f\n", installProgress_); + } + zip_fclose(zf); + fclose(f); + createdFiles.push_back(outFilename); + delete [] buffer; + } else { + ERROR_LOG(HLE, "Failed to open file for writing"); + } + } + } + INFO_LOG(HLE, "Extracted %i files (%i bytes / %i).", numFiles, (int)bytesCopied, (int)allBytes); + + zip_close(z); + z = 0; + installProgress_ = 1.0f; + installInProgress_ = false; + installError_ = ""; + if (deleteAfter) { + deleteFile(zipfile.c_str()); + } + InstallDone(); + return true; + +bail: + zip_close(z); + // We end up here if disk is full or couldn't write to storage for some other reason. + installProgress_ = 0.0f; + installInProgress_ = false; + installError_ = "Storage full"; + if (deleteAfter) { + deleteFile(zipfile.c_str()); + } + for (size_t i = 0; i < createdFiles.size(); i++) { + deleteFile(createdFiles[i].c_str()); + } + for (auto iter = createdDirs.begin(); iter != createdDirs.end(); ++iter) { + deleteDir(iter->c_str()); + } + InstallDone(); + return false; +} + +bool GameManager::InstallGameOnThread(std::string zipFile, bool deleteAfter) { + if (installInProgress_) { + return false; + } + + installThread_.reset(new std::thread(std::bind(&GameManager::InstallGame, this, zipFile, deleteAfter))); + installThread_->detach(); + return true; +} + +void GameManager::InstallDone() { + if (installThread_.get() != 0) { + installThread_.reset(); + } +} diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h new file mode 100644 index 0000000000..d5053a1446 --- /dev/null +++ b/Core/Util/GameManager.h @@ -0,0 +1,68 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + + +// Manages the PSP/GAME directory contents. +// +// Not concerned with full ISOs. + +#pragma once + +#include "thread/thread.h" +#include "net/http_client.h" + +class GameManager { +public: + GameManager(); + + bool IsGameInstalled(std::string name); + + // This starts off a background process. + bool DownloadAndInstall(std::string storeZipUrl); + bool Uninstall(std::string name); + + // Call from time to time to check on completed downloads from the + // main UI thread. + void Update(); + + // Returns false if no install is in progress. + bool IsInstallInProgress() const { + return installInProgress_; + } + float GetCurrentInstallProgress() const { + return installProgress_; + } + std::string GetInstallError() const { + return installError_; + } + + // Only returns false if there's already an installation in progress. + bool InstallGameOnThread(std::string zipFile, bool deleteAfter); + +private: + bool InstallGame(std::string zipfile, bool deleteAfter = false); + void InstallDone(); + + std::string GetTempFilename() const; + std::shared_ptr curDownload_; + std::shared_ptr installThread_; + bool installInProgress_; + float installProgress_; + std::string installError_; +}; + +extern GameManager g_GameManager; diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 09a8e4b008..db6f9a15ed 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "Core/Util/PPGeDraw.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" @@ -24,8 +25,8 @@ #include "Core/HLE/sceGe.h" #include "Core/MemMap.h" #include "image/zim_load.h" +#include "image/png_load.h" #include "util/text/utf8.h" -#include "MathUtil.h" #include "Core/System.h" static u32 atlasPtr; @@ -746,6 +747,20 @@ void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float EndVertexDataAndDraw(GE_PRIM_RECTANGLES); } +// Return a value such that (1 << value) >= x +int GetPow2(int x) +{ +#ifdef __GNUC__ + int ret = 31 - __builtin_clz(x|1); + if ((1 << ret) < x) +#else + int ret = 0; + while ((1 << ret) < x) +#endif + ret++; + return ret; +} + void PPGeSetDefaultTexture() { WriteCmd(GE_CMD_TEXTUREMAPENABLE, 1); @@ -789,3 +804,112 @@ void PPGeDisableTexture() WriteCmd(GE_CMD_TEXTUREMAPENABLE, 0); } +std::vector PPGeImage::loadedTextures_; + +PPGeImage::PPGeImage(const std::string &pspFilename) + : filename_(pspFilename), texture_(0) { +} + +PPGeImage::PPGeImage(u32 pngPointer, size_t pngSize) + : filename_(""), png_(pngPointer), size_(pngSize) { +} + +PPGeImage::~PPGeImage() { + Free(); +} + +bool PPGeImage::Load() { + Free(); + + // In case it fails to load. + width_ = 0; + height_ = 0; + + unsigned char *textureData; + int success; + if (filename_.empty()) { + success = pngLoadPtr(Memory::GetPointer(png_), size_, &width_, &height_, &textureData, false); + } else { + std::vector pngData; + if (pspFileSystem.ReadEntireFile(filename_, pngData) < 0) { + WARN_LOG(SCEGE, "Bad PPGeImage - cannot load file"); + return false; + } + + success = pngLoadPtr((const unsigned char *)&pngData[0], pngData.size(), &width_, &height_, &textureData, false); + } + if (!success) { + WARN_LOG(SCEGE, "Bad PPGeImage - not a valid png"); + return false; + } + + u32 texSize = width_ * height_ * 4; + texture_ = __PPGeDoAlloc(texSize, true, "Savedata Icon"); + if (texture_ == 0) { + WARN_LOG(SCEGE, "Bad PPGeImage - unable to allocate space for texture"); + return false; + } + + Memory::Memcpy(texture_, textureData, texSize); + free(textureData); + + lastFrame_ = gpuStats.numFlips; + loadedTextures_.push_back(this); + return true; +} + +void PPGeImage::Free() { + if (texture_ != 0) { + kernelMemory.Free(texture_); + texture_ = 0; + loadedTextures_.erase(std::remove(loadedTextures_.begin(), loadedTextures_.end(), this), loadedTextures_.end()); + } +} + +void PPGeImage::DoState(PointerWrap &p) { + auto s = p.Section("PPGeImage", 1); + if (!s) + return; + + p.Do(filename_); + p.Do(png_); + p.Do(size_); + p.Do(texture_); + p.Do(width_); + p.Do(height_); + p.Do(lastFrame_); +} + +void PPGeImage::CompatLoad(u32 texture, int width, int height) { + // Won't be reloadable, so don't add to loadedTextures_. + texture_ = texture; + width_ = width; + height_ = height; +} + +void PPGeImage::Decimate() { + static const int TOO_OLD_AGE = 30; + int tooOldFrame = gpuStats.numFlips - TOO_OLD_AGE; + for (size_t i = 0; i < loadedTextures_.size(); ++i) { + if (loadedTextures_[i]->lastFrame_ < tooOldFrame) { + loadedTextures_[i]->Free(); + // That altered loadedTextures_. + --i; + } + } +} + +void PPGeImage::SetTexture() { + if (texture_ == 0) { + Decimate(); + Load(); + } + + if (texture_ != 0) { + lastFrame_ = gpuStats.numFlips; + PPGeSetTexture(texture_, width_, height_); + } else { + PPGeDisableTexture(); + } +} + diff --git a/Core/Util/PPGeDraw.h b/Core/Util/PPGeDraw.h index bda1c4ea81..61ed4085e0 100644 --- a/Core/Util/PPGeDraw.h +++ b/Core/Util/PPGeDraw.h @@ -103,6 +103,48 @@ void PPGeDrawImage(int atlasImage, float x, float y, int align, u32 color = 0xFF void PPGeDrawImage(int atlasImage, float x, float y, float w, float h, int align, u32 color = 0xFFFFFFFF); void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float u2, float v2, int tw, int th, u32 color); +class PPGeImage { +public: + PPGeImage(const std::string &pspFilename); + PPGeImage(u32 pngPointer, size_t pngSize); + ~PPGeImage(); + + void SetTexture(); + + // Does not normally need to be called (except to force preloading.) + bool Load(); + void Free(); + + void DoState(PointerWrap &p); + + // Do not use, only for savestate upgrading. + void CompatLoad(u32 texture, int width, int height); + + int Width() { + return width_; + } + + int Height() { + return height_; + } + +private: + static void Decimate(); + static std::vector loadedTextures_; + + std::string filename_; + + // Only valid if filename_.empty(). + u32 png_; + size_t size_; + + u32 texture_; + int width_; + int height_; + + int lastFrame_; +}; + void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color); void PPGeSetDefaultTexture(); diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index e95a06615d..901443f245 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -38,22 +38,39 @@ enum GPUDebugBufferFormat { GPU_DBG_FORMAT_8888 = 3, GPU_DBG_FORMAT_INVALID = 0xFF, + // These are reversed versions. + GPU_DBG_FORMAT_REVERSE_FLAG = 4, + GPU_DBG_FORMAT_565_REV = 4, + GPU_DBG_FORMAT_5551_REV = 5, + GPU_DBG_FORMAT_4444_REV = 6, + // These don't, they're for depth/stencil buffers. GPU_DBG_FORMAT_FLOAT = 0x10, GPU_DBG_FORMAT_16BIT = 0x11, GPU_DBG_FORMAT_8BIT = 0x12, }; +inline GPUDebugBufferFormat &operator |=(GPUDebugBufferFormat &lhs, const GPUDebugBufferFormat &rhs) { + lhs = GPUDebugBufferFormat((int)lhs | (int)rhs); + return lhs; +} + struct GPUDebugBuffer { GPUDebugBuffer() : alloc_(false), data_(NULL) { } - GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt) + GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt, bool reversed = false) : alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(GPUDebugBufferFormat(fmt)), flipped_(false) { + if (reversed && fmt_ < GPU_DBG_FORMAT_8888) { + fmt_ |= GPU_DBG_FORMAT_REVERSE_FLAG; + } } - GPUDebugBuffer(void *data, u32 stride, u32 height, GETextureFormat fmt) + GPUDebugBuffer(void *data, u32 stride, u32 height, GETextureFormat fmt, bool reversed = false) : alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(GPUDebugBufferFormat(fmt)), flipped_(false) { + if (reversed && fmt_ < GPU_DBG_FORMAT_8888) { + fmt_ |= GPU_DBG_FORMAT_REVERSE_FLAG; + } } GPUDebugBuffer(void *data, u32 stride, u32 height, GPUDebugBufferFormat fmt) @@ -91,8 +108,12 @@ struct GPUDebugBuffer { return *this; } - void Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped = false) { - Allocate(stride, height, GPUDebugBufferFormat(fmt), flipped); + void Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped = false, bool reversed = false) { + GPUDebugBufferFormat actualFmt = GPUDebugBufferFormat(fmt); + if (reversed && actualFmt < GPU_DBG_FORMAT_8888) { + actualFmt |= GPU_DBG_FORMAT_REVERSE_FLAG; + } + Allocate(stride, height, actualFmt, flipped); } void Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped = false) { @@ -155,6 +176,14 @@ private: bool flipped_; }; +struct GPUDebugVertex { + float u; + float v; + float x; + float y; + float z; +}; + class GPUDebugInterface { public: virtual bool GetCurrentDisplayList(DisplayList &list) = 0; @@ -177,6 +206,10 @@ public: // Calling from a separate thread (e.g. UI) may fail. virtual void SetCmdValue(u32 op) = 0; + virtual bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + return false; + } + // Needs to be called from the GPU thread, so on the same thread as a notification is fine. // Calling from a separate thread (e.g. UI) may fail. virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index f89971cdda..3384efb10c 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -22,7 +22,6 @@ #include #include -#include "base/logging.h" #include "file/ini_file.h" #include "file/file_util.h" #include "file/vfs.h" @@ -46,6 +45,7 @@ void LoadPostShaderInfo(std::vector directories) { for (size_t d = 0; d < directories.size(); d++) { std::vector fileInfo; getFilesInDir(directories[d].c_str(), &fileInfo, "ini:"); + if (fileInfo.size() == 0) { // TODO: Really gotta fix the filter, now it's gonna open shaders as ini files.. VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:"); @@ -61,10 +61,10 @@ void LoadPostShaderInfo(std::vector directories) { name = name.substr(7); if (path.substr(0, 7) == "assets/") path = path.substr(7); - if (!ini.LoadFromVFS(name) && !ini.Load(fileInfo[f].fullName)) { - // vsh load. meh. - } else { + + if (ini.LoadFromVFS(name) || ini.Load(fileInfo[f].fullName)) { success = true; + // vsh load. meh. } if (!success) continue; @@ -91,7 +91,10 @@ void LoadPostShaderInfo(std::vector directories) { if (requiresIntegerSupport) continue; #endif - shaderInfo.erase(std::find(shaderInfo.begin(), shaderInfo.end(), info.name), shaderInfo.end()); + auto beginErase = std::find(shaderInfo.begin(), shaderInfo.end(), info.name); + if (beginErase != shaderInfo.end()) { + shaderInfo.erase(beginErase, shaderInfo.end()); + } shaderInfo.push_back(info); } } diff --git a/GPU/Common/TextureDecoder.cpp b/GPU/Common/TextureDecoder.cpp index 4d66ecd1a7..352ed4161d 100644 --- a/GPU/Common/TextureDecoder.cpp +++ b/GPU/Common/TextureDecoder.cpp @@ -24,12 +24,10 @@ #ifdef _M_SSE #include -#endif static u32 QuickTexHashSSE2(const void *checkp, u32 size) { u32 check = 0; -#ifdef _M_SSE if (((intptr_t)checkp & 0xf) == 0 && (size & 0x3f) == 0) { __m128i cursor = _mm_set1_epi32(0); __m128i cursor2 = _mm_set_epi16(0x0001U, 0x0083U, 0x4309U, 0x4d9bU, 0xb651U, 0x4b73U, 0x9bd9U, 0xc00bU); @@ -50,9 +48,6 @@ static u32 QuickTexHashSSE2(const void *checkp, u32 size) { cursor = _mm_add_epi32(cursor, _mm_srli_si128(cursor, 4)); check = _mm_cvtsi128_si32(cursor); } else { -#else - { -#endif const u32 *p = (const u32 *)checkp; for (u32 i = 0; i < size / 8; ++i) { check += *p++; @@ -62,6 +57,7 @@ static u32 QuickTexHashSSE2(const void *checkp, u32 size) { return check; } +#endif static u32 QuickTexHashBasic(const void *checkp, u32 size) { #if defined(ARM) && defined(__GNUC__) @@ -112,7 +108,7 @@ void SetupQuickTexHash() { #ifdef ARMV7 if (cpu_info.bNEON) DoQuickTexHash = &QuickTexHashNEON; -#else +#elif _M_SSE if (cpu_info.bSSE2) DoQuickTexHash = &QuickTexHashSSE2; #endif diff --git a/GPU/Common/TextureDecoderNEON.cpp b/GPU/Common/TextureDecoderNEON.cpp index fc7750a657..54e1dc62d4 100644 --- a/GPU/Common/TextureDecoderNEON.cpp +++ b/GPU/Common/TextureDecoderNEON.cpp @@ -29,7 +29,7 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { __builtin_prefetch(checkp, 0, 0); if (((intptr_t)checkp & 0xf) == 0 && (size & 0x3f) == 0) { -#if 0 +#ifdef IOS uint32x4_t cursor = vdupq_n_u32(0); uint32x4_t cursor2 = vld1q_u32((const u32 *)QuickTexHashInitial); uint32x4_t update = vdupq_n_u32(0x24552455U); @@ -48,10 +48,13 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { cursor = vaddq_u32(cursor, cursor2); check = vgetq_lane_u32(cursor, 0) + vgetq_lane_u32(cursor, 1) + vgetq_lane_u32(cursor, 2) + vgetq_lane_u32(cursor, 3); #else + // TODO: Why does this crash on iOS, but only certain devices? + // It's faster than the above, but I guess it sucks to be using an iPhone. + // d0/d1 (q0) - cursor // d2/d3 (q1) - cursor2 // d4/d5 (q2) - update - // d6-d13 (q3-q6) - memory transfer + // d16-d23 (q8-q11) - memory transfer asm volatile ( // Initialize cursor. "vmov.i32 q0, #0\n" @@ -66,7 +69,7 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { "movt r0, 0x4b73\n" "movw r1, 0x9bd9\n" "movt r1, 0xc00b\n" - "vmov d2, r0, r1\n" + "vmov d3, r0, r1\n" // Initialize update. "movw r0, 0x2455\n" @@ -81,14 +84,14 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { // Okay, do the memory hashing. "QuickTexHashNEON_next:\n" "pld [%2, #0xc0]\n" - "vldmia %2!, {d6-d13}\n" - "vmla.i32 q0, q1, q3\n" - "veor.i32 q0, q0, q4\n" - "vmul.i32 q6, q6, q1\n" + "vldmia %2!, {d16-d23}\n" + "vmla.i32 q0, q1, q8\n" + "vmul.i32 q11, q11, q1\n" + "veor.i32 q0, q0, q9\n" "cmp %2, r0\n" - "vadd.i32 q0, q0, q5\n" - "veor.i32 q0, q0, q6\n" + "vadd.i32 q0, q0, q10\n" "vadd.i32 q1, q1, q2\n" + "veor.i32 q0, q0, q11\n" "blo QuickTexHashNEON_next\n" // Now let's get the result. @@ -99,7 +102,7 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { : "=r"(check) : "r"(size), "r"(checkp) - : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13" + : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "cc" ); #endif } else { @@ -114,4 +117,4 @@ u32 QuickTexHashNEON(const void *checkp, u32 size) { } return check; -} \ No newline at end of file +} diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index e4ab616770..23378ec60e 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -42,7 +42,7 @@ int DecFmtSize(u8 fmt) { } } -void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { +void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { // Find index bounds. Could cache this in display lists. // Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck. int lowerBound = 0x7FFFFFFF; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 920a0b2dea..032935fa60 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -71,7 +71,7 @@ struct TransformedVertex u8 color1[4]; // prelit }; -void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); +void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); enum { STAT_VERTSSUBMITTED = 0, @@ -82,7 +82,6 @@ inline int RoundUp4(int x) { return (x + 3) & ~3; } -// Reads decoded vertex formats in a convenient way. For software transform and debugging. // Reads decoded vertex formats in a convenient way. For software transform and debugging. class VertexReader { diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index fa7add6596..259fd8eee0 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -79,11 +79,9 @@ void CenterRect(float *x, float *y, float *w, float *h, *x = 0.0f; *w = frameW; *h = frameW / origRatio; -#ifdef BLACKBERRY // Stretch a little bit if (g_Config.bPartialStretch) *h = (frameH + *h) / 2.0f; // (408 + 720) / 2 = 564 -#endif *y = (frameH - *h) / 2.0f; } else diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 455d621b97..68c9134686 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -732,7 +732,7 @@ void DIRECTX9_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_VERTEXTYPE: - if (diff) + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; @@ -1312,11 +1312,11 @@ void DIRECTX9_GPU::DoBlockTransfer() { ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); return; } - + // Do the copy! for (int y = 0; y < height; y++) { - const u8 *src = Memory::GetPointer(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp); - u8 *dst = Memory::GetPointer(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp); + const u8 *src = Memory::GetPointerUnchecked(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp); + u8 *dst = Memory::GetPointerUnchecked(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp); memcpy(dst, src, width * bpp); } @@ -1333,7 +1333,7 @@ void DIRECTX9_GPU::DoBlockTransfer() { if (((backBuffer != 0 && dstBasePtr == backBuffer) || (displayBuffer != 0 && dstBasePtr == displayBuffer)) && dstStride == 512 && height == 272) { - framebufferManager_.DrawPixels(Memory::GetPointer(dstBasePtr), GE_FORMAT_8888, 512); + framebufferManager_.DrawPixels(Memory::GetPointerUnchecked(dstBasePtr), GE_FORMAT_8888, 512); } } diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index 20d5463b34..bd50e801f8 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -212,7 +212,7 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) { // Depth Test dxstate.depthTest.enable(); dxstate.depthFunc.set(D3DCMP_ALWAYS); - dxstate.depthWrite.set(gstate.isClearModeDepthWriteEnabled()); + dxstate.depthWrite.set(gstate.isClearModeDepthMask()); // Color Test bool colorMask = (gstate.clearmode >> 8) & 1; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index c8b217f2c0..3c0b14b795 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -1092,7 +1092,7 @@ void *TextureCacheDX9::DecodeTextureLevel(GETextureFormat format, GEPaletteForma { dstFmt = getClutDestFormat(clutformat); - const bool mipmapShareClut = (gstate.texmode & 0x100) == 0; + const bool mipmapShareClut = gstate.isClutSharedForMipmaps(); const int clutSharingOffset = mipmapShareClut ? 0 : level * 16; switch (clutformat) { diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 95fbcd72ef..ba8f1ed677 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -99,6 +99,101 @@ static bool IsAlphaTestTriviallyTrue() { } } +const bool nonAlphaSrcFactors[16] = { + true, // GE_SRCBLEND_DSTCOLOR, + true, // GE_SRCBLEND_INVDSTCOLOR, + false, // GE_SRCBLEND_SRCALPHA, + false, // GE_SRCBLEND_INVSRCALPHA, + true, // GE_SRCBLEND_DSTALPHA, + true, // GE_SRCBLEND_INVDSTALPHA, + false, // GE_SRCBLEND_DOUBLESRCALPHA, + false, // GE_SRCBLEND_DOUBLEINVSRCALPHA, + true, // GE_SRCBLEND_DOUBLEDSTALPHA, + true, // GE_SRCBLEND_DOUBLEINVDSTALPHA, + true, // GE_SRCBLEND_FIXA, +}; + +const bool nonAlphaDestFactors[16] = { + true, // GE_DSTBLEND_SRCCOLOR, + true, // GE_DSTBLEND_INVSRCCOLOR, + false, // GE_DSTBLEND_SRCALPHA, + false, // GE_DSTBLEND_INVSRCALPHA, + true, // GE_DSTBLEND_DSTALPHA, + true, // GE_DSTBLEND_INVDSTALPHA, + false, // GE_DSTBLEND_DOUBLESRCALPHA, + false, // GE_DSTBLEND_DOUBLEINVSRCALPHA, + true, // GE_DSTBLEND_DOUBLEDSTALPHA, + true, // GE_DSTBLEND_DOUBLEINVDSTALPHA, + true, // GE_DSTBLEND_FIXB, +}; + +bool CanReplaceAlphaWithStencil() { + if (!gstate.isStencilTestEnabled()) { + return false; + } + if (gstate.isAlphaBlendEnabled()) { + return nonAlphaSrcFactors[gstate.getBlendFuncA()] && nonAlphaDestFactors[gstate.getBlendFuncA()]; + } + return true; +} + +StencilValueType ReplaceAlphaWithStencilType() { + switch (gstate.FrameBufFormat()) { + case GE_FORMAT_565: + // There's never a stencil value. Maybe the right alpha is 1? + return STENCIL_VALUE_ONE; + + case GE_FORMAT_5551: + switch (gstate.getStencilOpZPass()) { + // Technically, this should only ever use zero/one. + case GE_STENCILOP_REPLACE: + return (gstate.getStencilTestRef() & 0x80) != 0 ? STENCIL_VALUE_ONE : STENCIL_VALUE_ZERO; + + // Decrementing always zeros, since there's only one bit. + case GE_STENCILOP_DECR: + case GE_STENCILOP_ZERO: + return STENCIL_VALUE_ZERO; + + // Incrementing always fills, since there's only one bit. + case GE_STENCILOP_INCR: + return STENCIL_VALUE_ONE; + + case GE_STENCILOP_INVERT: + return STENCIL_VALUE_UNKNOWN; + + case GE_STENCILOP_KEEP: + return STENCIL_VALUE_KEEP; + } + break; + + case GE_FORMAT_4444: + case GE_FORMAT_8888: + case GE_FORMAT_INVALID: + switch (gstate.getStencilOpZPass()) { + case GE_STENCILOP_REPLACE: + return STENCIL_VALUE_UNIFORM; + + case GE_STENCILOP_ZERO: + if (gstate.getStencilOpZFail() == GE_STENCILOP_ZERO) { + return STENCIL_VALUE_ZERO; + } else { + return STENCIL_VALUE_KEEP; + } + + // Decrementing always zeros, since there's only one bit. + case GE_STENCILOP_DECR: + case GE_STENCILOP_INCR: + case GE_STENCILOP_INVERT: + return STENCIL_VALUE_UNKNOWN; + case GE_STENCILOP_KEEP: + return STENCIL_VALUE_KEEP; + } + break; + } + + return STENCIL_VALUE_UNKNOWN; +} + static bool IsColorTestTriviallyTrue() { GEComparison colorTestFunc = gstate.getColorTestFunction(); switch (colorTestFunc) { @@ -161,6 +256,7 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { bool enableAlphaDoubling = CanDoubleSrcBlendMode(); bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; bool doTextureAlpha = gstate.isTextureAlphaUsed(); + bool stencilToAlpha = CanReplaceAlphaWithStencil(); // All texfuncs except replace are the same for RGB as for RGBA with full alpha. if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) @@ -184,7 +280,10 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { id->d[0] |= (doTextureProjection & 1) << 16; id->d[0] |= (enableColorDoubling & 1) << 17; id->d[0] |= (enableAlphaDoubling & 1) << 18; - + if (stencilToAlpha) { + // 3 bits + id->d[0] |= ReplaceAlphaWithStencilType() << 19; + } if (enableAlphaTest) gpuStats.numAlphaTestedDraws++; else @@ -227,6 +326,7 @@ void GenerateFragmentShader(char *buffer) { bool enableAlphaDoubling = CanDoubleSrcBlendMode(); bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; bool doTextureAlpha = gstate.isTextureAlphaUsed(); + bool stencilToAlpha = !gstate.isModeClear() && CanReplaceAlphaWithStencil(); if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) doTextureAlpha = false; @@ -237,6 +337,9 @@ void GenerateFragmentShader(char *buffer) { if (enableAlphaTest || enableColorTest) { WRITE(p, "uniform vec4 u_alphacolorref;\n"); } + if (stencilToAlpha && ReplaceAlphaWithStencilType() == STENCIL_VALUE_UNIFORM) { + WRITE(p, "uniform float u_stencilReplaceValue;\n"); + } if (gstate.isTextureMapEnabled() && gstate.getTextureFunction() == GE_TEXFUNC_BLEND) WRITE(p, "uniform lowp vec3 u_texenv;\n"); @@ -302,6 +405,9 @@ void GenerateFragmentShader(char *buffer) { case GE_TEXFUNC_REPLACE: WRITE(p, " vec4 v = t%s;\n", secondary); break; case GE_TEXFUNC_ADD: + case GE_TEXFUNC_UNKNOWN1: + case GE_TEXFUNC_UNKNOWN2: + case GE_TEXFUNC_UNKNOWN3: WRITE(p, " vec4 v = vec4(p.rgb + t.rgb, p.a * t.a)%s;\n", secondary); break; default: WRITE(p, " vec4 v = p;\n"); break; @@ -318,6 +424,9 @@ void GenerateFragmentShader(char *buffer) { case GE_TEXFUNC_REPLACE: WRITE(p, " vec4 v = vec4(t.rgb, p.a)%s;\n", secondary); break; case GE_TEXFUNC_ADD: + case GE_TEXFUNC_UNKNOWN1: + case GE_TEXFUNC_UNKNOWN2: + case GE_TEXFUNC_UNKNOWN3: WRITE(p, " vec4 v = vec4(p.rgb + t.rgb, p.a)%s;\n", secondary); break; default: WRITE(p, " vec4 v = p;\n"); break; @@ -350,7 +459,7 @@ void GenerateFragmentShader(char *buffer) { } else if (enableAlphaDoubling) { WRITE(p, " v.a = v.a * 2.0;\n"); } - + if (enableColorTest) { GEComparison colorTestFunc = gstate.getColorTestFunction(); const char *colorTestFuncs[] = { "#", "#", " != ", " == " }; // never/always don't make sense @@ -373,6 +482,31 @@ void GenerateFragmentShader(char *buffer) { } } + if (stencilToAlpha) { + switch (ReplaceAlphaWithStencilType()) { + case STENCIL_VALUE_UNIFORM: + WRITE(p, " gl_FragColor.a = u_stencilReplaceValue;\n"); + break; + + case STENCIL_VALUE_ZERO: + WRITE(p, " gl_FragColor.a = 0.0;\n"); + break; + + case STENCIL_VALUE_ONE: + WRITE(p, " gl_FragColor.a = 1.0;\n"); + break; + + case STENCIL_VALUE_UNKNOWN: + // Maybe we should even mask away alpha using glColorMask and not change it at all? We do get here + // if the stencil mode is KEEP for example. + WRITE(p, " gl_FragColor.a = 0.0;\n"); + break; + + case STENCIL_VALUE_KEEP: + // Do nothing. We'll mask out the alpha using color mask. + break; + } + } #ifdef DEBUG_SHADER if (doTexture) { WRITE(p, " gl_FragColor = texture2D(tex, v_texcoord.xy);\n"); diff --git a/GPU/GLES/FragmentShaderGenerator.h b/GPU/GLES/FragmentShaderGenerator.h index bd4d53d9ce..e3e147f8e3 100644 --- a/GPU/GLES/FragmentShaderGenerator.h +++ b/GPU/GLES/FragmentShaderGenerator.h @@ -44,3 +44,14 @@ struct FragmentShaderID { void ComputeFragmentShaderID(FragmentShaderID *id); void GenerateFragmentShader(char *buffer); +enum StencilValueType { + STENCIL_VALUE_UNKNOWN, + STENCIL_VALUE_UNIFORM, + STENCIL_VALUE_ZERO, + STENCIL_VALUE_ONE, + STENCIL_VALUE_KEEP, +}; + +StencilValueType ReplaceAlphaWithStencilType(); +bool CanReplaceAlphaWithStencil(); + diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index f29dc626cc..40826593f0 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -19,6 +19,7 @@ #include "gfx_es2/gl_state.h" #include "gfx_es2/fbo.h" +#include "base/timeutil.h" #include "math/lin/matrix4x4.h" #include "Core/Host.h" @@ -26,6 +27,7 @@ #include "Core/Config.h" #include "Core/System.h" #include "Core/Reporting.h" +#include "Core/HLE/sceDisplay.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" @@ -133,11 +135,9 @@ void CenterRect(float *x, float *y, float *w, float *h, *x = 0.0f; *w = frameW; *h = frameW / origRatio; -#ifdef BLACKBERRY // Stretch a little bit if (g_Config.bPartialStretch) *h = (frameH + *h) / 2.0f; // (408 + 720) / 2 = 564 -#endif *y = (frameH - *h) / 2.0f; } else { // Image is taller than frame. Center horizontally. @@ -150,9 +150,12 @@ void CenterRect(float *x, float *y, float *w, float *h, } static void ClearBuffer() { + glstate.scissorTest.disable(); glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(0,0,0,1); + glstate.stencilFunc.set(GL_ALWAYS, 0xFF, 0xFF); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearStencil(0xFF); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -165,6 +168,7 @@ static void DisableState() { #if !defined(USING_GLES2) glstate.colorLogicOp.disable(); #endif + glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } void FramebufferManager::SetNumExtraFBOs(int num) { @@ -241,6 +245,10 @@ void FramebufferManager::CompileDraw2DProgram() { int pixelDeltaLoc = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); if (pixelDeltaLoc != -1) glUniform2f(pixelDeltaLoc, u_pixel_delta, v_pixel_delta); + timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); + if (timeLoc_ != -1) + glUniform4f(timeLoc_, 0.0f, 0.0f, 0.0f, 0.0f); + usePostShader_ = true; } } else { @@ -257,6 +265,10 @@ void FramebufferManager::DestroyDraw2DProgram() { glsl_destroy(draw2dprogram_); draw2dprogram_ = 0; } + if (plainColorProgram_) { + glsl_destroy(plainColorProgram_); + plainColorProgram_ = 0; + } if (postShaderProgram_) { glsl_destroy(postShaderProgram_); postShaderProgram_ = 0; @@ -277,8 +289,9 @@ FramebufferManager::FramebufferManager() : convBuf(0), draw2dprogram_(0), postShaderProgram_(0), - postShaderAtOutputResolution_(false), plainColorLoc_(-1), + timeLoc_(-1), + postShaderAtOutputResolution_(false), resized_(false), textureCache_(0), shaderManager_(0), @@ -314,7 +327,7 @@ FramebufferManager::~FramebufferManager() { delete [] convBuf; } -void FramebufferManager::DrawPixels(const u8 *framebuf, GEBufferFormat pixelFormat, int linesize) { +void FramebufferManager::DrawPixels(const u8 *framebuf, GEBufferFormat pixelFormat, int linesize, bool applyPostShader) { if (drawPixelsTex_ && drawPixelsTexFormat_ != pixelFormat) { glDeleteTextures(1, &drawPixelsTex_); drawPixelsTex_ = 0; @@ -407,16 +420,16 @@ void FramebufferManager::DrawPixels(const u8 *framebuf, GEBufferFormat pixelForm float x, y, w, h; CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight); - - glBindTexture(GL_TEXTURE_2D,drawPixelsTex_); - if (g_Config.iTexFiltering == LINEAR || (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos)) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } + glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 512, 272, GL_RGBA, GL_UNSIGNED_BYTE, useConvBuf ? convBuf : framebuf); - // This draws directly at the backbuffer so if there's a post shader, we need to apply it here. Should try to unify this path - // with the regular path somehow, but this simple solution works for most of the post shaders (it always runs at output resolution so FXAA may look odd). - if (usePostShader_) { + DisableState(); + + // This might draw directly at the backbuffer (if so, applyPostShader is set) so if there's a post shader, we need to apply it here. + // Should try to unify this path with the regular path somehow, but this simple solution works for most of the post shaders + // (it always runs at output resolution so FXAA may look odd). + if (applyPostShader && usePostShader_ && g_Config.iRenderingMode != 0) { DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, 480.0f / 512.0f, 1.0f, postShaderProgram_); } else { DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, 480.0f / 512.0f); @@ -460,16 +473,25 @@ void FramebufferManager::DrawPlainColor(u32 color) { } void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, bool flip, float uscale, float vscale, GLSLProgram *program) { + float u2 = uscale; + // Since we're flipping, 0 is down. That's where the scale goes. + float v1 = flip ? 1.0f : 1.0f - vscale; + float v2 = flip ? 1.0f - vscale : 1.0f; + + const float u1 = 0.0f; + const float texCoords[8] = {u1,v1, u2,v1, u2,v2, u1,v2}; + static const GLushort indices[4] = {0,1,3,2}; + if (texture) { // We know the texture, we can do a DrawTexture shortcut on nvidia. -#if defined(USING_GLES2) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(IOS) && !defined(BLACKBERRY) - if (gl_extensions.NV_draw_texture && !program) { +#if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(IOS) && !defined(BLACKBERRY) && !defined(MAEMO) + if (false && gl_extensions.NV_draw_texture && !program) { // Fast path for Tegra. TODO: Make this path work on desktop nvidia, seems GLEW doesn't have a clue. // Actually, on Desktop we should just use glBlitFramebuffer - although we take a texture here // so that's a little gnarly, will have to modify all callers. glDrawTextureNV(texture, 0, x, y, w, h, 0.0f, - 0, 0, uscale, vscale); + u1, v2, u2, v1); return; } #endif @@ -477,11 +499,6 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo glBindTexture(GL_TEXTURE_2D, texture); } - float u2 = uscale; - // Since we're flipping, 0 is down. That's where the scale goes. - float v1 = flip ? 1.0f : 1.0f - vscale; - float v2 = flip ? 1.0f - vscale : 1.0f; - float pos[12] = { x,y,0, x+w,y,0, @@ -494,8 +511,6 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo pos[i * 3 + 1] = -(pos[i * 3 + 1] / (destH * 0.5) - 1.0f); } - const float texCoords[8] = {0,v1, u2,v1, u2,v2, 0,v2}; - static const GLubyte indices[4] = {0,1,3,2}; if (!program) { if (!draw2dprogram_) { CompileDraw2DProgram(); @@ -505,13 +520,19 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo } glsl_bind(program); + if (program == postShaderProgram_ && timeLoc_ != -1) { + int flipCount = __DisplayGetFlipCount(); + int vCount = __DisplayGetVCount(); + float time[4] = {time_now(), (vCount % 60) * 1.0f/60.0f, (float)vCount, (float)(flipCount % 60)}; + glUniform4fv(timeLoc_, 1, time); + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glEnableVertexAttribArray(program->a_position); glEnableVertexAttribArray(program->a_texcoord0); glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices); glDisableVertexAttribArray(program->a_position); glDisableVertexAttribArray(program->a_texcoord0); @@ -612,12 +633,12 @@ void FramebufferManager::SetRenderFrameBuffer() { return; } - if (g_Config.iRenderingMode != 0 && g_Config.bWipeFramebufferAlpha && currentRenderVfb_) { + /* + if (g_Config.iRenderingMode != 0 && currentRenderVfb_) { // Hack is enabled, and there was a previous framebuffer. // Before we switch, let's do a series of trickery to copy one bit of stencil to // destination alpha. Or actually, this is just a bunch of hackery attempts on Wipeout. // Ignore for now. - /* glstate.depthTest.disable(); glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glstate.stencilTest.enable(); @@ -628,13 +649,14 @@ void FramebufferManager::SetRenderFrameBuffer() { //DrawPlainColor(0xFF000000); glstate.stencilTest.disable(); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - */ glstate.depthTest.disable(); glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); DrawPlainColor(0x00000000); shaderManager_->DirtyLastShader(); // dirty lastShader_ } + */ + gstate_c.framebufChanged = false; @@ -667,6 +689,10 @@ void FramebufferManager::SetRenderFrameBuffer() { vfb = v; // Update fb stride in case it changed vfb->fb_stride = fb_stride; + if (v->width < drawing_width && v->height < drawing_height) { + v->width = drawing_width; + v->height = drawing_height; + } if (v->format != fmt) { v->width = drawing_width; v->height = drawing_height; @@ -715,8 +741,6 @@ void FramebufferManager::SetRenderFrameBuffer() { vfb->colorDepth = FBO_565; break; case GE_FORMAT_8888: - vfb->colorDepth = FBO_8888; - break; default: vfb->colorDepth = FBO_8888; break; @@ -727,6 +751,7 @@ void FramebufferManager::SetRenderFrameBuffer() { vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, vfb->colorDepth); if (vfb->fbo) { fbo_bind_as_render_target(vfb->fbo); + glstate.viewport.restore(); } else { ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); } @@ -742,7 +767,7 @@ void FramebufferManager::SetRenderFrameBuffer() { frameLastFramebufUsed = gpuStats.numFlips; vfbs_.push_back(vfb); ClearBuffer(); - glEnable(GL_DITHER); + glEnable(GL_DITHER); // why? currentRenderVfb_ = vfb; INFO_LOG(SCEGE, "Creating FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); @@ -751,12 +776,23 @@ void FramebufferManager::SetRenderFrameBuffer() { bool sharingReported = false; for (size_t i = 0, end = vfbs_.size(); i < end; ++i) { if (MaskedEqual(fb_address, vfbs_[i]->z_address)) { - WARN_LOG_REPORT(SCEGE, "FBO created from existing depthbuffer (unsupported), %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); + // If it's clearing it, most likely it just needs more video memory. + // Technically it could write something interesting and the other might not clear, but that's not likely. + if (!gstate.isModeClear() || !gstate.isClearModeColorMask() || !gstate.isClearModeAlphaMask()) { + WARN_LOG_REPORT(SCEGE, "FBO created from existing depthbuffer as color, %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); + } } else if (MaskedEqual(z_address, vfbs_[i]->fb_address)) { - WARN_LOG_REPORT(SCEGE, "FBO using other buffer as depthbuffer (unsupported), %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); + // If it's clearing it, then it's probably just the reverse of the above case. + if (!gstate.isModeClear() || !gstate.isClearModeDepthMask()) { + WARN_LOG_REPORT(SCEGE, "FBO using existing buffer as depthbuffer, %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); + } } else if (MaskedEqual(z_address, vfbs_[i]->z_address) && fb_address != vfbs_[i]->fb_address && !sharingReported) { - WARN_LOG_REPORT(SCEGE, "FBO sharing existing depthbuffer (unsupported), %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); - sharingReported = true; + // This happens a lot, but virtually always it's cleared. + // It's possible the other might not clear, but when every game is reported it's not useful. + if (!gstate.isModeClear() || !gstate.isClearModeDepthMask()) { + WARN_LOG_REPORT(SCEGE, "FBO reusing depthbuffer, %08x/%08x and %08x/%08x", fb_address, z_address, vfbs_[i]->fb_address, vfbs_[i]->z_address); + sharingReported = true; + } } } @@ -861,8 +897,8 @@ void FramebufferManager::CopyDisplayToOutput() { } if (!vfb) { - // Just a pointer to plain memory to draw. Draw it. - DrawPixels(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_); + // Just a pointer to plain memory to draw. We should create a framebuffer, then draw to it. + DrawPixels(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_, true); return; } } else { @@ -911,6 +947,7 @@ void FramebufferManager::CopyDisplayToOutput() { } else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. fbo_bind_as_render_target(extraFBOs_[0]); + glstate.viewport.restore(); int fbo_w, fbo_h; fbo_get_dimensions(extraFBOs_[0], &fbo_w, &fbo_h); glstate.viewport.set(0, 0, fbo_w, fbo_h); @@ -1010,6 +1047,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s nvfb->last_frame_render = gpuStats.numFlips; bvfbs_.push_back(nvfb); fbo_bind_as_render_target(nvfb->fbo); + glstate.viewport.restore(); ClearBuffer(); glEnable(GL_DITHER); } else { @@ -1021,6 +1059,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s #ifdef USING_GLES2 if (nvfb->fbo) { fbo_bind_as_render_target(nvfb->fbo); + glstate.viewport.restore(); } // Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering @@ -1053,6 +1092,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFramebuffer *dst, bool flip, float upscale, float vscale) { if (dst->fbo) { fbo_bind_as_render_target(dst->fbo); + glstate.viewport.restore(); } else { ERROR_LOG_REPORT_ONCE(dstfbozero, SCEGE, "BlitFramebuffer_: dst->fbo == 0"); fbo_unbind(); @@ -1430,7 +1470,7 @@ void FramebufferManager::DecimateFBOs() { VirtualFramebuffer *vfb = vfbs_[i]; int age = frameLastFramebufUsed - std::max(vfb->last_frame_render, vfb->last_frame_used); - if (updateVram && age == 0 && !vfb->memoryUpdated && vfb == displayFramebuf_) + if (updateVram && age == 0 && !vfb->memoryUpdated) ReadFramebufferToMemory(vfb); if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) { @@ -1495,6 +1535,7 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { DisableState(); glstate.viewport.set(0, 0, vfb->renderWidth, vfb->renderHeight); fbo_bind_as_render_target(vfb->fbo); + glstate.viewport.restore(); needUnbind = true; DrawPixels(Memory::GetPointer(addr | 0x04000000), vfb->format, vfb->fb_stride); } else { @@ -1529,7 +1570,7 @@ bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { return true; } - buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GE_FORMAT_8888, true); + buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GE_FORMAT_8888, true, true); if (vfb->fbo) fbo_bind_for_read(vfb->fbo); #ifndef USING_GLES2 diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 3caf665782..b118d272e0 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -114,7 +114,7 @@ public: shaderManager_ = sm; } - void DrawPixels(const u8 *framebuf, GEBufferFormat pixelFormat, int linesize); + void DrawPixels(const u8 *framebuf, GEBufferFormat pixelFormat, int linesize, bool applyPostShader = false); // If texture != 0, will bind it. void DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, bool flip = false, float uscale = 1.0f, float vscale = 1.0f, GLSLProgram *program = 0); @@ -204,6 +204,7 @@ private: GLSLProgram *plainColorProgram_; GLSLProgram *postShaderProgram_; int plainColorLoc_; + int timeLoc_; TextureCache *textureCache_; ShaderManager *shaderManager_; diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index b1f359c88d..0d0968b14d 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -18,6 +18,7 @@ #include "base/logging.h" #include "gfx_es2/gl_state.h" +#include "Core/Debugger/Breakpoints.h" #include "Core/MemMap.h" #include "Core/Host.h" #include "Core/Config.h" @@ -149,7 +150,7 @@ static const CommandTableEntry commandTable[] = { {GE_CMD_CULLFACEENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_DITHERENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_STENCILOP, FLAG_FLUSHBEFOREONCHANGE}, - {GE_CMD_STENCILTEST, FLAG_FLUSHBEFOREONCHANGE}, + {GE_CMD_STENCILTEST, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE}, {GE_CMD_STENCILTESTENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_ALPHABLENDENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_BLENDMODE, FLAG_FLUSHBEFOREONCHANGE}, @@ -430,6 +431,10 @@ GLES_GPU::GLES_GPU() commandFlags_[GE_CMD_TEXOFFSETV] &= ~FLAG_FLUSHBEFOREONCHANGE; } + if (g_Config.bSoftwareSkinning) { + commandFlags_[GE_CMD_VERTEXTYPE] &= ~FLAG_FLUSHBEFOREONCHANGE; + } + BuildReportingInfo(); } @@ -733,7 +738,7 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { #endif int bytesRead; - transformDraw_.SubmitPrim(verts, inds, prim, count, gstate.vertType, -1, &bytesRead); + transformDraw_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead); int vertexCost = transformDraw_.EstimatePerVertexCost(); gpuStats.vertexGPUCycles += vertexCost * count; @@ -849,7 +854,7 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { currentList->bboxResult = true; break; } - if ((data % 8 == 0) && data < 64) { // Sanity check + if (((data & 7) == 0) && data <= 64) { // Sanity check void *control_points = Memory::GetPointer(gstate_c.vertexAddr); if (gstate.vertType & GE_VTYPE_IDX_MASK) { ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Indexed bounding box data not supported."); @@ -868,8 +873,21 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { break; case GE_CMD_VERTEXTYPE: - if (diff) - shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + if (diff) { + if (!g_Config.bSoftwareSkinning) { + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + } else { + if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { + // Restore and flush + gstate.vertType ^= diff; + Flush(); + gstate.vertType ^= diff; + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + } + } + } break; case GE_CMD_REGION1: @@ -994,8 +1012,6 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { } break; - case GE_CMD_CLUTADDR: - case GE_CMD_CLUTADDRUPPER: case GE_CMD_CLUTFORMAT: if (diff) { gstate_c.textureChanged = true; @@ -1003,6 +1019,11 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { // This could be used to "dirty" textures with clut. break; + case GE_CMD_CLUTADDR: + case GE_CMD_CLUTADDRUPPER: + // Hm, LOADCLUT actually changes the CLUT so no need to dirty here. + break; + case GE_CMD_LOADCLUT: gstate_c.textureChanged = true; textureCache_.LoadClut(); @@ -1042,9 +1063,15 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { } case GE_CMD_TEXSIZE0: - gstate_c.curTextureWidth = gstate.getTextureWidth(0); - gstate_c.curTextureHeight = gstate.getTextureHeight(0); - shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + // Render to texture may have overridden the width/height. + // Don't reset it unless the size is different / the texture has changed. + if (diff || gstate_c.textureChanged) { + gstate_c.curTextureWidth = gstate.getTextureWidth(0); + gstate_c.curTextureHeight = gstate.getTextureHeight(0); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + // We will need to reset the texture now. + gstate_c.textureChanged = true; + } //fall thru - ignoring the mipmap sizes for now case GE_CMD_TEXSIZE1: @@ -1054,7 +1081,9 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_TEXSIZE5: case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: - gstate_c.textureChanged = true; + if (diff) { + gstate_c.textureChanged = true; + } break; case GE_CMD_ZBUFPTR: @@ -1160,9 +1189,9 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: if (diff) { - float r = (float)(data & 0xff)/255.0f; - float g = (float)((data>>8) & 0xff)/255.0f; - float b = (float)(data>>16)/255.0f; + float r = (float)(data & 0xff) * (1.0f / 255.0f); + float g = (float)((data >> 8) & 0xff) * (1.0f / 255.0f); + float b = (float)(data >> 16) * (1.0f / 255.0f); int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; @@ -1291,10 +1320,10 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_WORLDMATRIXDATA: { int num = gstate.worldmtxnum & 0xF; - float newVal = getFloat24(data); - if (num < 12 && newVal != gstate.worldMatrix[num]) { + u32 newVal = data << 8; + if (num < 12 && newVal != ((const u32 *)gstate.worldMatrix)[num]) { Flush(); - gstate.worldMatrix[num] = newVal; + ((u32 *)gstate.worldMatrix)[num] = newVal; shaderManager_->DirtyUniform(DIRTY_WORLDMATRIX); } num++; @@ -1309,10 +1338,10 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_VIEWMATRIXDATA: { int num = gstate.viewmtxnum & 0xF; - float newVal = getFloat24(data); - if (num < 12 && newVal != gstate.viewMatrix[num]) { + u32 newVal = data << 8; + if (num < 12 && newVal != ((const u32 *)gstate.viewMatrix)[num]) { Flush(); - gstate.viewMatrix[num] = newVal; + ((u32 *)gstate.viewMatrix)[num] = newVal; shaderManager_->DirtyUniform(DIRTY_VIEWMATRIX); } num++; @@ -1327,10 +1356,10 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_PROJMATRIXDATA: { int num = gstate.projmtxnum & 0xF; - float newVal = getFloat24(data); - if (newVal != gstate.projMatrix[num]) { + u32 newVal = data << 8; + if (newVal != ((const u32 *)gstate.projMatrix)[num]) { Flush(); - gstate.projMatrix[num] = newVal; + ((u32 *)gstate.projMatrix)[num] = newVal; shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); } num++; @@ -1345,10 +1374,10 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_TGENMATRIXDATA: { int num = gstate.texmtxnum & 0xF; - float newVal = getFloat24(data); - if (num < 12 && newVal != gstate.tgenMatrix[num]) { + u32 newVal = data << 8; + if (num < 12 && newVal != ((const u32 *)gstate.tgenMatrix)[num]) { Flush(); - gstate.tgenMatrix[num] = newVal; + ((u32 *)gstate.tgenMatrix)[num] = newVal; shaderManager_->DirtyUniform(DIRTY_TEXMATRIX); } num++; @@ -1363,11 +1392,15 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { case GE_CMD_BONEMATRIXDATA: { int num = gstate.boneMatrixNumber & 0x7F; - float newVal = getFloat24(data); - if (num < 96 && newVal != gstate.boneMatrix[num]) { - Flush(); - gstate.boneMatrix[num] = newVal; - shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); + u32 newVal = data << 8; + if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) { + // Bone matrices should NOT flush when software skinning is enabled! + // TODO: Also check for morph... + if (!g_Config.bSoftwareSkinning) { + Flush(); + shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); + } + ((u32 *)gstate.boneMatrix)[num] = newVal; } num++; gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x7F); @@ -1375,16 +1408,6 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { break; #ifndef USING_GLES2 - case GE_CMD_LOGICOPENABLE: - if (data != 0) - ERROR_LOG_REPORT_ONCE(logicOpEnable, G3D, "Unsupported logic op enabled: %x", data); - break; - - case GE_CMD_LOGICOP: - if (data != 0) - ERROR_LOG_REPORT_ONCE(logicOp, G3D, "Unsupported logic op: %06x", data); - break; - case GE_CMD_ANTIALIASENABLE: if (data != 0) WARN_LOG_REPORT_ONCE(antiAlias, G3D, "Unsupported antialias enabled: %06x", data); @@ -1405,6 +1428,22 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { break; #endif + // Handled in StateMapping. + case GE_CMD_STENCILTEST: + if (diff) { + shaderManager_->DirtyUniform(DIRTY_STENCILREPLACEVALUE); + } + break; + case GE_CMD_STENCILOP: + break; + + case GE_CMD_MASKRGB: + case GE_CMD_MASKALPHA: + break; + + case GE_CMD_REVERSENORMAL: + break; + case GE_CMD_UNKNOWN_03: case GE_CMD_UNKNOWN_0D: case GE_CMD_UNKNOWN_11: @@ -1487,7 +1526,7 @@ void GLES_GPU::DoBlockTransfer() { int bpp = gstate.getTransferBpp(); DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - + if (!Memory::IsValidAddress(srcBasePtr)) { ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); return; @@ -1499,15 +1538,19 @@ void GLES_GPU::DoBlockTransfer() { } // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) + // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them + // entirely by walking a couple of pointers... for (int y = 0; y < height; y++) { - const u8 *src = Memory::GetPointer(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp); - u8 *dst = Memory::GetPointer(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp); + const u8 *src = Memory::GetPointerUnchecked(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp); + u8 *dst = Memory::GetPointerUnchecked(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp); memcpy(dst, src, width * bpp); } // TODO: Notify all overlapping FBOs that they need to reload. textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); + if (Memory::IsRAMAddress(srcBasePtr) && Memory::IsVRAMAddress(dstBasePtr)) + framebufferManager_.UpdateFromMemory(dstBasePtr, (dstY + height) * dstStride * bpp, true); // A few games use this INSTEAD of actually drawing the video image to the screen, they just blast it to // the backbuffer. Detect this and have the framebuffermanager draw the pixels. @@ -1518,8 +1561,13 @@ void GLES_GPU::DoBlockTransfer() { if (((backBuffer != 0 && dstBasePtr == backBuffer) || (displayBuffer != 0 && dstBasePtr == displayBuffer)) && dstStride == 512 && height == 272) { - framebufferManager_.DrawPixels(Memory::GetPointer(dstBasePtr), GE_FORMAT_8888, 512); + framebufferManager_.DrawPixels(Memory::GetPointerUnchecked(dstBasePtr), GE_FORMAT_8888, 512); } + +#ifndef USING_GLES2 + CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); +#endif } void GLES_GPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { @@ -1570,7 +1618,8 @@ void GLES_GPU::DoState(PointerWrap &p) { // TODO: Some of these things may not be necessary. // None of these are necessary when saving. - if (p.mode == p.MODE_READ) { + // In Freeze-Frame mode, we don't want to do any of this. + if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { textureCache_.Clear(true); transformDraw_.ClearTrackedVertexArrays(); @@ -1612,3 +1661,15 @@ bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) { return false; #endif } + +bool GLES_GPU::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + return transformDraw_.GetCurrentSimpleVertices(count, vertices, indices); +} + +bool GLES_GPU::DescribeCodePtr(const u8 *ptr, std::string &name) { + if (transformDraw_.IsCodePtrVertexDecoder(ptr)) { + name = "VertexDecoderJit"; + return true; + } + return false; +} diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 7ad6bb6863..6746e77770 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -71,6 +71,9 @@ public: bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentTexture(GPUDebugBuffer &buffer); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); + + virtual bool DescribeCodePtr(const u8 *ptr, std::string &name); protected: virtual void FastRunLoop(DisplayList &list); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 6a900a25a2..456bd831e0 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -26,6 +26,7 @@ #include #include "base/logging.h" +#include "math/math_util.h" #include "gfx_es2/gl_state.h" #include "math/lin/matrix4x4.h" @@ -141,6 +142,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans u_fogcoef = glGetUniformLocation(program, "u_fogcoef"); u_alphacolorref = glGetUniformLocation(program, "u_alphacolorref"); u_colormask = glGetUniformLocation(program, "u_colormask"); + u_stencilReplaceValue = glGetUniformLocation(program, "u_stencilReplaceValue"); // Transform u_view = glGetUniformLocation(program, "u_view"); @@ -198,6 +200,36 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans if (-1 != glGetAttribLocation(program, "color0")) attrMask |= 1 << ATTR_COLOR0; if (-1 != glGetAttribLocation(program, "color1")) attrMask |= 1 << ATTR_COLOR1; + availableUniforms = 0; + if (u_proj != -1) availableUniforms |= DIRTY_PROJMATRIX; + if (u_proj_through != -1) availableUniforms |= DIRTY_PROJTHROUGHMATRIX; + if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV; + if (u_alphacolorref != -1) availableUniforms |= DIRTY_ALPHACOLORREF; + if (u_colormask != -1) availableUniforms |= DIRTY_COLORMASK; + if (u_fogcolor != -1) availableUniforms |= DIRTY_FOGCOLOR; + if (u_fogcoef != -1) availableUniforms |= DIRTY_FOGCOEF; + if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV; + if (u_uvscaleoffset != -1) availableUniforms |= DIRTY_UVSCALEOFFSET; + if (u_world != -1) availableUniforms |= DIRTY_WORLDMATRIX; + if (u_view != -1) availableUniforms |= DIRTY_VIEWMATRIX; + if (u_texmtx != -1) availableUniforms |= DIRTY_TEXMATRIX; + // Looping up to numBones lets us avoid checking u_bone[i] + for (int i = 0; i < numBones; i++) { + if (u_bone[i] != -1) + availableUniforms |= DIRTY_BONEMATRIX0 << i; + } + if (u_ambient != -1) availableUniforms |= DIRTY_AMBIENT; + if (u_matambientalpha != -1) availableUniforms |= DIRTY_MATAMBIENTALPHA; + if (u_matdiffuse != -1) availableUniforms |= DIRTY_MATDIFFUSE; + if (u_matemissive != -1) availableUniforms |= DIRTY_MATEMISSIVE; + if (u_matspecular != -1) availableUniforms |= DIRTY_MATSPECULAR; + for (int i = 0; i < 4; i++) { + if (u_lightdir[i] != -1 || + u_lightspecular[i] != -1 || + u_lightpos[i] != -1) + availableUniforms |= DIRTY_LIGHT0 << i; + } + glUseProgram(program); // Default uniform values @@ -290,7 +322,7 @@ static void SetMatrix4x3(int uniform, const float *m4x3) { void LinkedShader::use(u32 vertType, LinkedShader *previous) { glUseProgram(program); - updateUniforms(vertType); + UpdateUniforms(vertType); int enable, disable; if (previous) { enable = attrMask & ~previous->attrMask; @@ -314,12 +346,14 @@ void LinkedShader::stop() { } } -void LinkedShader::updateUniforms(u32 vertType) { - if (!dirtyUniforms) +void LinkedShader::UpdateUniforms(u32 vertType) { + u32 dirty = dirtyUniforms & availableUniforms; + dirtyUniforms = 0; + if (!dirty) return; // Update any dirty uniforms before we draw - if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) { + if (dirty & DIRTY_PROJMATRIX) { float flippedMatrix[16]; memcpy(flippedMatrix, gstate.projMatrix, 16 * sizeof(float)); if (gstate_c.vpHeight < 0) { @@ -332,77 +366,116 @@ void LinkedShader::updateUniforms(u32 vertType) { } glUniformMatrix4fv(u_proj, 1, GL_FALSE, flippedMatrix); } - if (u_proj_through != -1 && (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX)) + if (dirty & DIRTY_PROJTHROUGHMATRIX) { Matrix4x4 proj_through; proj_through.setOrtho(0.0f, gstate_c.curRTWidth, gstate_c.curRTHeight, 0, 0, 1); glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr()); } - if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) { + if (dirty & DIRTY_TEXENV) { SetColorUniform3(u_texenv, gstate.texenvcolor); } - if (u_alphacolorref != -1 && (dirtyUniforms & DIRTY_ALPHACOLORREF)) { + if (dirty & DIRTY_ALPHACOLORREF) { SetColorUniform3Alpha255(u_alphacolorref, gstate.getColorTestRef(), gstate.getAlphaTestRef()); } - if (u_colormask != -1 && (dirtyUniforms & DIRTY_COLORMASK)) { + if (dirty & DIRTY_COLORMASK) { SetColorUniform3(u_colormask, gstate.colormask); } - if (u_fogcolor != -1 && (dirtyUniforms & DIRTY_FOGCOLOR)) { + if (dirty & DIRTY_FOGCOLOR) { SetColorUniform3(u_fogcolor, gstate.fogcolor); } - if (u_fogcoef != -1 && (dirtyUniforms & DIRTY_FOGCOEF)) { - const float fogcoef[2] = { + if (dirty & DIRTY_FOGCOEF) { + float fogcoef[2] = { getFloat24(gstate.fog1), getFloat24(gstate.fog2), }; + if (my_isinf(fogcoef[1])) { + // not really sure what a sensible value might be. + fogcoef[1] = 10000.0f; + } glUniform2fv(u_fogcoef, 1, fogcoef); } // Texturing - if (u_uvscaleoffset != -1 && (dirtyUniforms & DIRTY_UVSCALEOFFSET)) { + + // If this dirty check is changed to true, Frontier Gate Boost works in texcoord speedhack mode. + // This means that it's not a flushing issue. + // It uses GE_TEXMAP_TEXTURE_MATRIX with GE_PROJMAP_UV a lot. + // Can't figure out why it doesn't dirty at the right points though... + if (dirty & DIRTY_UVSCALEOFFSET) { + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + const float widthFactor = (float)w * invW; + const float heightFactor = (float)h * invH; + + static const float rescale[4] = {1.0f, 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f}; + const float factor = rescale[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT]; + float uvscaleoff[4]; - if (gstate.isModeThrough()) { - // We never get here because we don't use HW transform with through mode. - // Although - why don't we? - uvscaleoff[0] = gstate_c.uv.uScale / (float)gstate_c.curTextureWidth; - uvscaleoff[1] = gstate_c.uv.vScale / (float)gstate_c.curTextureHeight; - uvscaleoff[2] = gstate_c.uv.uOff / (float)gstate_c.curTextureWidth; - uvscaleoff[3] = gstate_c.uv.vOff / (float)gstate_c.curTextureHeight; - glUniform4fv(u_uvscaleoffset, 1, uvscaleoff); - } else { - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - float widthFactor = (float)w / (float)gstate_c.curTextureWidth; - float heightFactor = (float)h / (float)gstate_c.curTextureHeight; + + switch (gstate.getUVGenMode()) { + case GE_TEXMAP_TEXTURE_COORDS: // Not sure what GE_TEXMAP_UNKNOWN is, but seen in Riviera. Treating the same as GE_TEXMAP_TEXTURE_COORDS works. - if (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN) { - static const float rescale[4] = {1.0f, 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f}; - float factor = rescale[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT]; - uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor; - uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor; - uvscaleoff[2] = gstate_c.uv.uOff * widthFactor; - uvscaleoff[3] = gstate_c.uv.vOff * heightFactor; - } else { + case GE_TEXMAP_UNKNOWN: + if (g_Config.bPrescaleUV) { + // Shouldn't even get here as we won't use the uniform in the shader. + // We are here but are prescaling UV in the decoder? Let's do the same as in the other case + // except consider *Scale and *Off to be 1 and 0. uvscaleoff[0] = widthFactor; uvscaleoff[1] = heightFactor; uvscaleoff[2] = 0.0f; uvscaleoff[3] = 0.0f; + } else { + uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor; + uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor; + uvscaleoff[2] = gstate_c.uv.uOff * widthFactor; + uvscaleoff[3] = gstate_c.uv.vOff * heightFactor; } - glUniform4fv(u_uvscaleoffset, 1, uvscaleoff); + break; + + // These two work the same whether or not we prescale UV. + + case GE_TEXMAP_TEXTURE_MATRIX: + // We cannot bake the UV coord scale factor in here, as we apply a matrix multiplication + // before this is applied, and the matrix multiplication may contain translation. In this case + // the translation will be scaled which breaks faces in Hexyz Force for example. + // So I've gone back to applying the scale factor in the shader. + uvscaleoff[0] = widthFactor; + uvscaleoff[1] = heightFactor; + uvscaleoff[2] = 0.0f; + uvscaleoff[3] = 0.0f; + break; + + case GE_TEXMAP_ENVIRONMENT_MAP: + // In this mode we only use uvscaleoff to scale to the texture size. + uvscaleoff[0] = widthFactor; + uvscaleoff[1] = heightFactor; + uvscaleoff[2] = 0.0f; + uvscaleoff[3] = 0.0f; + break; + + default: + ERROR_LOG_REPORT(G3D, "Unexpected UV gen mode: %d", gstate.getUVGenMode()); } + glUniform4fv(u_uvscaleoffset, 1, uvscaleoff); } // Transform - if (u_world != -1 && (dirtyUniforms & DIRTY_WORLDMATRIX)) { + if (dirty & DIRTY_WORLDMATRIX) { SetMatrix4x3(u_world, gstate.worldMatrix); } - if (u_view != -1 && (dirtyUniforms & DIRTY_VIEWMATRIX)) { + if (dirty & DIRTY_VIEWMATRIX) { SetMatrix4x3(u_view, gstate.viewMatrix); } - if (u_texmtx != -1 && (dirtyUniforms & DIRTY_TEXMATRIX)) { + if (dirty & DIRTY_TEXMATRIX) { SetMatrix4x3(u_texmtx, gstate.tgenMatrix); } + if (dirty & DIRTY_STENCILREPLACEVALUE) { + glUniform1f(u_stencilReplaceValue, gstate.getStencilTestRef()); + } // TODO: Could even set all bones in one go if they're all dirty. #ifdef USE_BONE_ARRAY if (u_bone != -1) { @@ -410,7 +483,7 @@ void LinkedShader::updateUniforms(u32 vertType) { bool allDirty = true; for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { + if (dirty & (DIRTY_BONEMATRIX0 << i)) { ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, allBones + 16 * i); } else { allDirty = false; @@ -422,7 +495,7 @@ void LinkedShader::updateUniforms(u32 vertType) { } else { // Set them one by one. Could try to coalesce two in a row etc but too lazy. for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { + if (dirty & (DIRTY_BONEMATRIX0 << i)) { glUniformMatrix4fv(u_bone + i, 1, GL_FALSE, allBones + 16 * i); } } @@ -431,7 +504,7 @@ void LinkedShader::updateUniforms(u32 vertType) { #else float bonetemp[16]; for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { + if (dirty & (DIRTY_BONEMATRIX0 << i)) { ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, bonetemp); glUniformMatrix4fv(u_bone[i], 1, GL_FALSE, bonetemp); } @@ -439,31 +512,31 @@ void LinkedShader::updateUniforms(u32 vertType) { #endif // Lighting - if (u_ambient != -1 && (dirtyUniforms & DIRTY_AMBIENT)) { + if (dirty & DIRTY_AMBIENT) { SetColorUniform3Alpha(u_ambient, gstate.ambientcolor, gstate.getAmbientA()); } - if (u_matambientalpha != -1 && (dirtyUniforms & DIRTY_MATAMBIENTALPHA)) { + if (dirty & DIRTY_MATAMBIENTALPHA) { SetColorUniform3Alpha(u_matambientalpha, gstate.materialambient, gstate.getMaterialAmbientA()); } - if (u_matdiffuse != -1 && (dirtyUniforms & DIRTY_MATDIFFUSE)) { + if (dirty & DIRTY_MATDIFFUSE) { SetColorUniform3(u_matdiffuse, gstate.materialdiffuse); } - if (u_matemissive != -1 && (dirtyUniforms & DIRTY_MATEMISSIVE)) { + if (dirty & DIRTY_MATEMISSIVE) { SetColorUniform3(u_matemissive, gstate.materialemissive); } - if (u_matspecular != -1 && (dirtyUniforms & DIRTY_MATSPECULAR)) { + if (dirty & DIRTY_MATSPECULAR) { SetColorUniform3ExtraFloat(u_matspecular, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); } for (int i = 0; i < 4; i++) { - if (dirtyUniforms & (DIRTY_LIGHT0 << i)) { + if (dirty & (DIRTY_LIGHT0 << i)) { if (gstate.isDirectionalLight(i)) { // Prenormalize float x = gstate_c.lightpos[i][0]; float y = gstate_c.lightpos[i][1]; float z = gstate_c.lightpos[i][2]; float len = sqrtf(x*x+y*y+z*z); - if (len == 0.0f) + if (len == 0.0f) len = 1.0f; else len = 1.0f / len; @@ -481,8 +554,6 @@ void LinkedShader::updateUniforms(u32 vertType) { if (u_lightspecular[i] != -1) glUniform3fv(u_lightspecular[i], 1, gstate_c.lightColor[2][i]); } } - - dirtyUniforms = 0; } ShaderManager::ShaderManager() : lastShader_(NULL), globalDirty_(0xFFFFFFFF), shaderSwitchDirty_(0) { @@ -534,8 +605,10 @@ void ShaderManager::DirtyLastShader() { // disables vertex arrays LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) { - if (g_Config.bPrescaleUV) - globalDirty_ &= ~DIRTY_UVSCALEOFFSET; + // This doesn't work - we miss some events that really do need to dirty the prescale. + // like changing the texmapmode. + // if (g_Config.bPrescaleUV) + // globalDirty_ &= ~DIRTY_UVSCALEOFFSET; if (globalDirty_) { if (lastShader_) @@ -553,7 +626,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) { // Just update uniforms if this is the same shader as last time. if (lastShader_ != 0 && VSID == lastVSID_ && FSID == lastFSID_) { - lastShader_->updateUniforms(vertType); + lastShader_->UpdateUniforms(vertType); return lastShader_; // Already all set. } diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index f5f1450579..9c18a12516 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -45,17 +45,19 @@ public: void use(u32 vertType, LinkedShader *previous); void stop(); - void updateUniforms(u32 vertType); + void UpdateUniforms(u32 vertType); // Set to false if the VS failed, happens on Mali-400 a lot for complex shaders. bool useHWTransform_; uint32_t program; + u32 availableUniforms; u32 dirtyUniforms; // Present attributes in the shader. int attrMask; // 1 << ATTR_ ... or-ed together. + int u_stencilReplaceValue; int u_tex; int u_proj; int u_proj_through; @@ -104,7 +106,10 @@ enum DIRTY_FOGCOEF = (1 << 3), DIRTY_TEXENV = (1 << 4), DIRTY_ALPHACOLORREF = (1 << 5), - DIRTY_COLORREF = (1 << 6), + + // 1 << 6 is free! Wait, not anymore... + DIRTY_STENCILREPLACEVALUE = (1 << 6), + DIRTY_COLORMASK = (1 << 7), DIRTY_LIGHT0 = (1 << 8), DIRTY_LIGHT1 = (1 << 9), @@ -116,7 +121,9 @@ enum DIRTY_MATEMISSIVE = (1 << 14), DIRTY_AMBIENT = (1 << 15), DIRTY_MATAMBIENTALPHA = (1 << 16), - DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a + + // 1 << 17 is free! + DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares" DIRTY_WORLDMATRIX = (1 << 21), diff --git a/GPU/GLES/SoftwareTransform.cpp b/GPU/GLES/SoftwareTransform.cpp new file mode 100644 index 0000000000..5c7e167326 --- /dev/null +++ b/GPU/GLES/SoftwareTransform.cpp @@ -0,0 +1,680 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "gfx_es2/gl_state.h" + +#include "Core/Config.h" +#include "GPU/GPUState.h" +#include "GPU/Math3D.h" +#include "GPU/GLES/ShaderManager.h" +#include "GPU/GLES/TransformPipeline.h" + +// This is the software transform pipeline, which is necessary for supporting RECT +// primitives correctly without geometry shaders, and may be easier to use for +// debugging than the hardware transform pipeline. + +// There's code here that simply expands transformed RECTANGLES into plain triangles. + +// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0. +// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of +// this code. + +// Actually, if we find the camera-relative right and down vectors, it might even be possible to add the extra points in pre-transformed +// space and thus make decent use of hardware transform. + +// Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for +// GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. +// + +extern const GLuint glprim[8]; + +// Check for max first as clamping to max is more common than min when lighting. +inline float clamp(float in, float min, float max) { + return in > max ? max : (in < min ? min : in); +} + +// Convenient way to do precomputation to save the parts of the lighting calculation +// that's common between the many vertices of a draw call. +class Lighter { +public: + Lighter(); + void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f normal); + +private: + Color4 globalAmbient; + Color4 materialEmissive; + Color4 materialAmbient; + Color4 materialDiffuse; + Color4 materialSpecular; + float specCoef_; + // Vec3f viewer_; + bool doShadeMapping_; + int materialUpdate_; +}; + +Lighter::Lighter() { + doShadeMapping_ = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP; + materialEmissive.GetFromRGB(gstate.materialemissive); + materialEmissive.a = 0.0f; + globalAmbient.GetFromRGB(gstate.ambientcolor); + globalAmbient.GetFromA(gstate.ambientalpha); + materialAmbient.GetFromRGB(gstate.materialambient); + materialAmbient.GetFromA(gstate.materialalpha); + materialDiffuse.GetFromRGB(gstate.materialdiffuse); + materialDiffuse.a = 1.0f; + materialSpecular.GetFromRGB(gstate.materialspecular); + materialSpecular.a = 1.0f; + specCoef_ = getFloat24(gstate.materialspecularcoef); + // viewer_ = Vec3f(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); + materialUpdate_ = gstate.materialupdate & 7; +} + +void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f norm) +{ + Color4 in(colorIn); + + const Color4 *ambient; + if (materialUpdate_ & 1) + ambient = ∈ + else + ambient = &materialAmbient; + + const Color4 *diffuse; + if (materialUpdate_ & 2) + diffuse = ∈ + else + diffuse = &materialDiffuse; + + const Color4 *specular; + if (materialUpdate_ & 4) + specular = ∈ + else + specular = &materialSpecular; + + Color4 lightSum0 = globalAmbient * *ambient + materialEmissive; + Color4 lightSum1(0, 0, 0, 0); + + for (int l = 0; l < 4; l++) + { + // can we skip this light? + if (!gstate.isLightChanEnabled(l)) + continue; + + GELightType type = gstate.getLightType(l); + + Vec3f toLight(0,0,0); + Vec3f lightDir(0,0,0); + + if (type == GE_LIGHTTYPE_DIRECTIONAL) + toLight = Vec3f(gstate_c.lightpos[l]); // lightdir is for spotlights + else + toLight = Vec3f(gstate_c.lightpos[l]) - pos; + + bool doSpecular = gstate.isUsingSpecularLight(l); + bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l); + + float distanceToLight = toLight.Length(); + float dot = 0.0f; + float angle = 0.0f; + float lightScale = 0.0f; + + if (distanceToLight > 0.0f) { + toLight /= distanceToLight; + dot = Dot(toLight, norm); + } + // Clamp dot to zero. + if (dot < 0.0f) dot = 0.0f; + + if (poweredDiffuse) + dot = powf(dot, specCoef_); + + // Attenuation + switch (type) { + case GE_LIGHTTYPE_DIRECTIONAL: + lightScale = 1.0f; + break; + case GE_LIGHTTYPE_POINT: + lightScale = clamp(1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight), 0.0f, 1.0f); + break; + case GE_LIGHTTYPE_SPOT: + case GE_LIGHTTYPE_UNKNOWN: + lightDir = gstate_c.lightdir[l]; + angle = Dot(toLight.Normalized(), lightDir.Normalized()); + if (angle >= gstate_c.lightangle[l]) + lightScale = clamp(1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, gstate_c.lightspotCoef[l]); + break; + default: + // ILLEGAL + break; + } + + Color4 lightDiff(gstate_c.lightColor[1][l], 0.0f); + Color4 diff = (lightDiff * *diffuse) * dot; + + // Real PSP specular + Vec3f toViewer(0,0,1); + // Better specular + // Vec3f toViewer = (viewer - pos).Normalized(); + + if (doSpecular) + { + Vec3f halfVec = (toLight + toViewer); + halfVec.Normalize(); + + dot = Dot(halfVec, norm); + if (dot > 0.0f) + { + Color4 lightSpec(gstate_c.lightColor[2][l], 0.0f); + lightSum1 += (lightSpec * *specular * (powf(dot, specCoef_) * lightScale)); + } + } + + if (gstate.isLightChanEnabled(l)) + { + Color4 lightAmbient(gstate_c.lightColor[0][l], 0.0f); + lightSum0 += (lightAmbient * *ambient + diff) * lightScale; + } + } + + // 4? + for (int i = 0; i < 4; i++) { + colorOut0[i] = lightSum0[i] > 1.0f ? 1.0f : lightSum0[i]; + colorOut1[i] = lightSum1[i] > 1.0f ? 1.0f : lightSum1[i]; + } +} + +// The verts are in the order: BR BL TL TR +static void SwapUVs(TransformedVertex &a, TransformedVertex &b) { + float tempu = a.u; + float tempv = a.v; + a.u = b.u; + a.v = b.v; + b.u = tempu; + b.v = tempv; +} + +// 2 3 3 2 0 3 2 1 +// to to or +// 1 0 0 1 1 2 3 0 + + +// See comment below where this was called before. +/* +static void RotateUV(TransformedVertex v[4]) { + float x1 = v[2].x; + float x2 = v[0].x; + float y1 = v[2].y; + float y2 = v[0].y; + + if ((x1 < x2 && y1 < y2) || (x1 > x2 && y1 > y2)) + SwapUVs(v[1], v[3]); +}*/ + +static void RotateUVThrough(TransformedVertex v[4]) { + float x1 = v[2].x; + float x2 = v[0].x; + float y1 = v[2].y; + float y2 = v[0].y; + + if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) + SwapUVs(v[1], v[3]); +} + +// Clears on the PSP are best done by drawing a series of vertical strips +// in clear mode. This tries to detect that. +bool TransformDrawEngine::IsReallyAClear(int numVerts) const { + if (transformed[0].x != 0.0f || transformed[0].y != 0.0f) + return false; + + u32 matchcolor; + memcpy(&matchcolor, transformed[0].color0, 4); + float matchz = transformed[0].z; + + int bufW = gstate_c.curRTWidth; + int bufH = gstate_c.curRTHeight; + + float prevX = 0.0f; + for (int i = 1; i < numVerts; i++) { + u32 vcolor; + memcpy(&vcolor, transformed[i].color0, 4); + if (vcolor != matchcolor || transformed[i].z != matchz) + return false; + + if ((i & 1) == 0) { + // Top left of a rectangle + if (transformed[i].y != 0) + return false; + if (i > 0 && transformed[i].x != transformed[i - 1].x) + return false; + } else { + // Bottom right + if (transformed[i].y != bufH) + return false; + if (transformed[i].x <= transformed[i - 1].x) + return false; + } + } + + // The last vertical strip often extends outside the drawing area. + if (transformed[numVerts - 1].x < bufW) + return false; + + return true; +} + + +void TransformDrawEngine::SoftwareTransformAndDraw( + int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { + + bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; + bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled(); + + // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. + +#if defined(USING_GLES2) + if (vertexCount > 0x10000/3) + vertexCount = 0x10000/3; +#endif + + float uscale = 1.0f; + float vscale = 1.0f; + bool scaleUV = false; + if (throughmode) { + uscale /= gstate_c.curTextureWidth; + vscale /= gstate_c.curTextureHeight; + } else { + scaleUV = !g_Config.bPrescaleUV; + } + + bool skinningEnabled = vertTypeIsSkinningEnabled(vertType); + + int w = gstate.getTextureWidth(0); + int h = gstate.getTextureHeight(0); + float widthFactor = (float) w / (float) gstate_c.curTextureWidth; + float heightFactor = (float) h / (float) gstate_c.curTextureHeight; + + Lighter lighter; + float fog_end = getFloat24(gstate.fog1); + float fog_slope = getFloat24(gstate.fog2); + + VertexReader reader(decoded, decVtxFormat, vertType); + for (int index = 0; index < maxIndex; index++) { + reader.Goto(index); + + float v[3] = {0, 0, 0}; + float c0[4] = {1, 1, 1, 1}; + float c1[4] = {0, 0, 0, 0}; + float uv[3] = {0, 0, 1}; + float fogCoef = 1.0f; + + if (throughmode) { + // Do not touch the coordinates or the colors. No lighting. + reader.ReadPos(v); + if (reader.hasColor0()) { + reader.ReadColor0(c0); + for (int j = 0; j < 4; j++) { + c1[j] = 0.0f; + } + } else { + c0[0] = gstate.getMaterialAmbientR() / 255.f; + c0[1] = gstate.getMaterialAmbientG() / 255.f; + c0[2] = gstate.getMaterialAmbientB() / 255.f; + c0[3] = gstate.getMaterialAmbientA() / 255.f; + } + + if (reader.hasUV()) { + reader.ReadUV(uv); + + uv[0] *= uscale; + uv[1] *= vscale; + } + fogCoef = 1.0f; + // Scale UV? + } else { + // We do software T&L for now + float out[3], norm[3]; + float pos[3], nrm[3]; + Vec3f normal(0, 0, 1); + reader.ReadPos(pos); + if (reader.hasNormal()) + reader.ReadNrm(nrm); + + if (!skinningEnabled) { + Vec3ByMatrix43(out, pos, gstate.worldMatrix); + if (reader.hasNormal()) { + Norm3ByMatrix43(norm, nrm, gstate.worldMatrix); + normal = Vec3f(norm).Normalized(); + } + } else { + float weights[8]; + reader.ReadWeights(weights); + // Skinning + Vec3f psum(0,0,0); + Vec3f nsum(0,0,0); + for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) { + if (weights[i] != 0.0f) { + Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12); + Vec3f tpos(out); + psum += tpos * weights[i]; + if (reader.hasNormal()) { + Norm3ByMatrix43(norm, nrm, gstate.boneMatrix+i*12); + Vec3f tnorm(norm); + nsum += tnorm * weights[i]; + } + } + } + + // Yes, we really must multiply by the world matrix too. + Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix); + if (reader.hasNormal()) { + Norm3ByMatrix43(norm, nsum.AsArray(), gstate.worldMatrix); + normal = Vec3f(norm).Normalized(); + } + } + + // Perform lighting here if enabled. don't need to check through, it's checked above. + float unlitColor[4] = {1, 1, 1, 1}; + if (reader.hasColor0()) { + reader.ReadColor0(unlitColor); + } else { + unlitColor[0] = gstate.getMaterialAmbientR() / 255.f; + unlitColor[1] = gstate.getMaterialAmbientG() / 255.f; + unlitColor[2] = gstate.getMaterialAmbientB() / 255.f; + unlitColor[3] = gstate.getMaterialAmbientA() / 255.f; + } + float litColor0[4]; + float litColor1[4]; + lighter.Light(litColor0, litColor1, unlitColor, out, normal); + + if (gstate.isLightingEnabled()) { + // Don't ignore gstate.lmode - we should send two colors in that case + for (int j = 0; j < 4; j++) { + c0[j] = litColor0[j]; + } + if (lmode) { + // Separate colors + for (int j = 0; j < 4; j++) { + c1[j] = litColor1[j]; + } + } else { + // Summed color into c0 + for (int j = 0; j < 4; j++) { + c0[j] = ((c0[j] + litColor1[j]) > 1.0f) ? 1.0f : (c0[j] + litColor1[j]); + } + } + } else { + if (reader.hasColor0()) { + for (int j = 0; j < 4; j++) { + c0[j] = unlitColor[j]; + } + } else { + c0[0] = gstate.getMaterialAmbientR() / 255.f; + c0[1] = gstate.getMaterialAmbientG() / 255.f; + c0[2] = gstate.getMaterialAmbientB() / 255.f; + c0[3] = gstate.getMaterialAmbientA() / 255.f; + } + if (lmode) { + for (int j = 0; j < 4; j++) { + c1[j] = 0.0f; + } + } + } + + float ruv[2] = {0.0f, 0.0f}; + if (reader.hasUV()) + reader.ReadUV(ruv); + + // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. + switch (gstate.getUVGenMode()) { + case GE_TEXMAP_TEXTURE_COORDS: // UV mapping + case GE_TEXMAP_UNKNOWN: // Seen in Riviera. Unsure of meaning, but this works. + // Texture scale/offset is only performed in this mode. + if (scaleUV) { + uv[0] = ruv[0]*gstate_c.uv.uScale + gstate_c.uv.uOff; + uv[1] = ruv[1]*gstate_c.uv.vScale + gstate_c.uv.vOff; + } else { + uv[0] = ruv[0]; + uv[1] = ruv[1]; + } + uv[2] = 1.0f; + break; + + case GE_TEXMAP_TEXTURE_MATRIX: + { + // Projection mapping + Vec3f source; + switch (gstate.getUVProjMode()) { + case GE_PROJMAP_POSITION: // Use model space XYZ as source + source = pos; + break; + + case GE_PROJMAP_UV: // Use unscaled UV as source + source = Vec3f(ruv[0], ruv[1], 0.0f); + break; + + case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source + if (reader.hasNormal()) { + source = Vec3f(norm).Normalized(); + } else { + ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?"); + source = Vec3f(0.0f, 0.0f, 1.0f); + } + break; + + case GE_PROJMAP_NORMAL: // Use non-normalized normal as source! + if (reader.hasNormal()) { + source = Vec3f(norm); + } else { + ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?"); + source = Vec3f(0.0f, 0.0f, 1.0f); + } + break; + } + + float uvw[3]; + Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix); + uv[0] = uvw[0]; + uv[1] = uvw[1]; + uv[2] = uvw[2]; + } + break; + + case GE_TEXMAP_ENVIRONMENT_MAP: + // Shade mapping - use two light sources to generate U and V. + { + Vec3f lightpos0 = Vec3f(gstate_c.lightpos[gstate.getUVLS0()]).Normalized(); + Vec3f lightpos1 = Vec3f(gstate_c.lightpos[gstate.getUVLS1()]).Normalized(); + + uv[0] = (1.0f + Dot(lightpos0, normal))/2.0f; + uv[1] = (1.0f - Dot(lightpos1, normal))/2.0f; + uv[2] = 1.0f; + } + break; + + default: + // Illegal + ERROR_LOG_REPORT(G3D, "Impossible UV gen mode? %d", gstate.getUVGenMode()); + break; + } + + uv[0] = uv[0] * widthFactor; + uv[1] = uv[1] * heightFactor; + + // Transform the coord by the view matrix. + Vec3ByMatrix43(v, out, gstate.viewMatrix); + fogCoef = (v[2] + fog_end) * fog_slope; + } + + // TODO: Write to a flexible buffer, we don't always need all four components. + memcpy(&transformed[index].x, v, 3 * sizeof(float)); + transformed[index].fog = fogCoef; + memcpy(&transformed[index].u, uv, 3 * sizeof(float)); + if (gstate_c.flipTexture) { + transformed[index].v = 1.0f - transformed[index].v; + } + for (int i = 0; i < 4; i++) { + transformed[index].color0[i] = c0[i] * 255.0f; + } + for (int i = 0; i < 3; i++) { + transformed[index].color1[i] = c1[i] * 255.0f; + } + } + + // Here's the best opportunity to try to detect rectangles used to clear the screen, and + // replace them with real OpenGL clears. This can provide a speedup on certain mobile chips. + // Disabled for now - depth does not come out exactly the same. + // + // An alternative option is to simply ditch all the verts except the first and last to create a single + // rectangle out of many. Quite a small optimization though. + if (false && maxIndex > 1 && gstate.isModeClear() && prim == GE_PRIM_RECTANGLES && IsReallyAClear(maxIndex)) { + u32 clearColor; + memcpy(&clearColor, transformed[0].color0, 4); + float clearDepth = transformed[0].z; + const float col[4] = { + ((clearColor & 0xFF)) / 255.0f, + ((clearColor & 0xFF00) >> 8) / 255.0f, + ((clearColor & 0xFF0000) >> 16) / 255.0f, + ((clearColor & 0xFF000000) >> 24) / 255.0f, + }; + + bool colorMask = gstate.isClearModeColorMask(); + bool alphaMask = gstate.isClearModeAlphaMask(); + glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask); + if (alphaMask) { + glstate.stencilTest.set(true); + // Clear stencil + // TODO: extract the stencilValue properly, see below + int stencilValue = 0; + glstate.stencilFunc.set(GL_ALWAYS, stencilValue, 255); + } else { + // Don't touch stencil + glstate.stencilTest.set(false); + } + glstate.scissorTest.set(false); + bool depthMask = gstate.isClearModeDepthMask(); + + int target = 0; + if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + if (depthMask) target |= GL_DEPTH_BUFFER_BIT; + + glClearColor(col[0], col[1], col[2], col[3]); +#ifdef USING_GLES2 + glClearDepthf(clearDepth); +#else + glClearDepth(clearDepth); +#endif + glClearStencil(0); // TODO - take from alpha? + glClear(target); + return; + } + + // Step 2: expand rectangles. + const TransformedVertex *drawBuffer = transformed; + int numTrans = 0; + + bool drawIndexed = false; + + if (prim != GE_PRIM_RECTANGLES) { + // We can simply draw the unexpanded buffer. + numTrans = vertexCount; + drawIndexed = true; + } else { + numTrans = 0; + drawBuffer = transformedExpanded; + TransformedVertex *trans = &transformedExpanded[0]; + TransformedVertex saved; + u32 stencilValue = 0; + for (int i = 0; i < vertexCount; i += 2) { + int index = ((const u16*)inds)[i]; + saved = transformed[index]; + int index2 = ((const u16*)inds)[i + 1]; + TransformedVertex &transVtx = transformed[index2]; + if (i == 0) + stencilValue = transVtx.color0[3]; + // We have to turn the rectangle into two triangles, so 6 points. Sigh. + + // bottom right + trans[0] = transVtx; + + // bottom left + trans[1] = transVtx; + trans[1].y = saved.y; + trans[1].v = saved.v; + + // top left + trans[2] = transVtx; + trans[2].x = saved.x; + trans[2].y = saved.y; + trans[2].u = saved.u; + trans[2].v = saved.v; + + // top right + trans[3] = transVtx; + trans[3].x = saved.x; + trans[3].u = saved.u; + + // That's the four corners. Now process UV rotation. + if (throughmode) + RotateUVThrough(trans); + + // Apparently, non-through RotateUV just breaks things. + // If we find a game where it helps, we'll just have to figure out how they differ. + // Possibly, it has something to do with flipped viewport Y axis, which a few games use. + // One game might be one of the Metal Gear ones, can't find the issue right now though. + // else + // RotateUV(trans); + + // bottom right + trans[4] = trans[0]; + + // top left + trans[5] = trans[2]; + trans += 6; + + numTrans += 6; + } + + // We don't know the color until here, so we have to do it now, instead of in StateMapping. + // Might want to reconsider the order of things later... + if (gstate.isModeClear() && gstate.isClearModeAlphaMask()) { + glstate.stencilFunc.set(GL_ALWAYS, stencilValue, 255); + } + } + + // TODO: Add a post-transform cache here for multi-RECTANGLES only. + // Might help for text drawing. + + // these spam the gDebugger log. + const int vertexSize = sizeof(transformed[0]); + + bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; + glBindBuffer(GL_ARRAY_BUFFER, 0); + glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); + int attrMask = program->attrMask; + if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4); + if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4); + if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 8 * 4); + if (drawIndexed) { +#if 1 // USING_GLES2 + glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds); +#else + glDrawRangeElements(glprim[prim], 0, indexGen.MaxIndex(), numTrans, GL_UNSIGNED_SHORT, inds); +#endif + } else { + glDrawArrays(glprim[prim], 0, numTrans); + } +} diff --git a/GPU/GLES/Spline.cpp b/GPU/GLES/Spline.cpp index ffd5ce2769..2c59e53194 100644 --- a/GPU/GLES/Spline.cpp +++ b/GPU/GLES/Spline.cpp @@ -49,7 +49,7 @@ u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inP }; // Let's have two separate loops, one for non skinning and one for skinning. - if ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { + if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { int numBoneWeights = vertTypeGetNumBoneWeights(vertType); for (int i = lowerBound; i <= upperBound; i++) { reader.Goto(i); @@ -736,8 +736,22 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; - SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, -1, 0); + UVScale prevUVScale; + if (g_Config.bPrescaleUV) { + // We scaled during Normalize already so let's turn it off when drawing. + prevUVScale = gstate_c.uv; + gstate_c.uv.uScale = 1.0f; + gstate_c.uv.vScale = 1.0f; + gstate_c.uv.uOff = 0; + gstate_c.uv.vOff = 0; + } + SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, 0); + Flush(); + + if (g_Config.bPrescaleUV) { + gstate_c.uv = prevUVScale; + } } void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) { @@ -811,6 +825,20 @@ void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; - SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, -1, 0); + UVScale prevUVScale; + if (g_Config.bPrescaleUV) { + // We scaled during Normalize already so let's turn it off when drawing. + prevUVScale = gstate_c.uv; + gstate_c.uv.uScale = 1.0f; + gstate_c.uv.vScale = 1.0f; + gstate_c.uv.uOff = 0; + gstate_c.uv.vOff = 0; + } + + SubmitPrim(decoded2, quadIndices_, GE_PRIM_TRIANGLES, count, vertTypeWithIndex16, 0); Flush(); + + if (g_Config.bPrescaleUV) { + gstate_c.uv = prevUVScale; + } } diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 41206eb026..c9045c2735 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -33,6 +33,7 @@ #include "GPU/GLES/ShaderManager.h" #include "GPU/GLES/TextureCache.h" #include "GPU/GLES/Framebuffer.h" +#include "GPU/GLES/FragmentShaderGenerator.h" static const GLushort aLookup[11] = { GL_DST_COLOR, @@ -101,8 +102,8 @@ static const GLushort stencilOps[] = { GL_ZERO, GL_REPLACE, GL_INVERT, - GL_INCR_WRAP, - GL_DECR_WRAP, // don't know if these should be wrap or not + GL_INCR, + GL_DECR, GL_KEEP, // reserved GL_KEEP, // reserved }; @@ -178,6 +179,13 @@ void TransformDrawEngine::ApplyDrawState(int prim) { if (blendFuncA > GE_SRCBLEND_FIXA) blendFuncA = GE_SRCBLEND_FIXA; if (blendFuncB > GE_DSTBLEND_FIXB) blendFuncB = GE_DSTBLEND_FIXB; + float constantAlpha = 1.0f; + if (gstate.isStencilTestEnabled() && !CanReplaceAlphaWithStencil()) { + if (gstate.isStencilTestEnabled() == STENCIL_VALUE_UNIFORM) { + constantAlpha = gstate.getStencilTestRef() * (1.0f / 255.0f); + } + } + // Shortcut by using GL_ONE where possible, no need to set blendcolor GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? blendColor2Func(gstate.getFixA()) : aLookup[blendFuncA]; GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? blendColor2Func(gstate.getFixB()) : bLookup[blendFuncB]; @@ -186,24 +194,24 @@ void TransformDrawEngine::ApplyDrawState(int prim) { Vec3f fixB = Vec3f::FromRGB(gstate.getFixB()); if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB != GL_INVALID_ENUM) { // Can use blendcolor trivially. - const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f}; + const float blendColor[4] = {fixA.x, fixA.y, fixA.z, constantAlpha}; glstate.blendColor.set(blendColor); glBlendFuncA = GL_CONSTANT_COLOR; } else if (glBlendFuncA != GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) { // Can use blendcolor trivially. - const float blendColor[4] = {fixB.x, fixB.y, fixB.z, 1.0f}; + const float blendColor[4] = {fixB.x, fixB.y, fixB.z, constantAlpha}; glstate.blendColor.set(blendColor); glBlendFuncB = GL_CONSTANT_COLOR; } else if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) { - if (blendColorSimilar(fixA, Vec3f::AssignToAll(1.0f) - fixB)) { + if (blendColorSimilar(fixA, Vec3f::AssignToAll(constantAlpha) - fixB)) { glBlendFuncA = GL_CONSTANT_COLOR; glBlendFuncB = GL_ONE_MINUS_CONSTANT_COLOR; - const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f}; + const float blendColor[4] = {fixA.x, fixA.y, fixA.z, constantAlpha}; glstate.blendColor.set(blendColor); } else if (blendColorSimilar(fixA, fixB)) { glBlendFuncA = GL_CONSTANT_COLOR; glBlendFuncB = GL_CONSTANT_COLOR; - const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f}; + const float blendColor[4] = {fixA.x, fixA.y, fixA.z, constantAlpha}; glstate.blendColor.set(blendColor); } else { static bool didReportBlend = false; @@ -218,17 +226,32 @@ void TransformDrawEngine::ApplyDrawState(int prim) { if (nearZeroA || blendColorSimilar(fixA, Vec3f::AssignToAll(1.0f), 0.25f)) { glBlendFuncA = nearZeroA ? GL_ZERO : GL_ONE; glBlendFuncB = GL_CONSTANT_COLOR; - const float blendColor[4] = {fixB.x, fixB.y, fixB.z, 1.0f}; + const float blendColor[4] = {fixB.x, fixB.y, fixB.z, constantAlpha}; glstate.blendColor.set(blendColor); // We need to pick something. Let's go with A as the fixed color. } else { glBlendFuncA = GL_CONSTANT_COLOR; glBlendFuncB = nearZeroB ? GL_ZERO : GL_ONE; - const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f}; + const float blendColor[4] = {fixA.x, fixA.y, fixA.z, constantAlpha}; glstate.blendColor.set(blendColor); } } + } else { + // We optimized both, but that's probably not necessary, so let's pick one to be constant. + // For now let's just pick whichever was fixed instead of checking error. + if (blendFuncA == GE_SRCBLEND_FIXA) { + glBlendFuncA = GL_CONSTANT_COLOR; + const float blendColor[4] = {fixA.x, fixA.y, fixA.z, constantAlpha}; + glstate.blendColor.set(blendColor); + } else { + glBlendFuncB = GL_CONSTANT_COLOR; + const float blendColor[4] = {fixB.x, fixB.y, fixB.z, constantAlpha}; + glstate.blendColor.set(blendColor); + } } + } else if (constantAlpha < 1.0f) { + const float blendColor[4] = {1.0f, 1.0f, 1.0f, constantAlpha}; + glstate.blendColor.set(blendColor); } // Some Android devices (especially Mali, it seems) composite badly if there's alpha in the backbuffer. @@ -243,13 +266,38 @@ void TransformDrawEngine::ApplyDrawState(int prim) { #endif // At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set right somehow. - if (!gstate.isStencilTestEnabled() && gstate.isDepthWriteEnabled()) { - // Fixes some Persona 2 issues, may be correct? (that is, don't change dest alpha at all if blending) - // If this doesn't break anything else, it's likely to be right. - // I guess an alternative solution would be to simply disable alpha writes if alpha blending is enabled. - glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ZERO); + + // The stencil-to-alpha in fragment shader doesn't apply here (blending is enabled), and we shouldn't + // do any blending in the alpha channel as that doesn't seem to happen on PSP. So lacking a better option, + // the only value we can set alpha to here without multipass and dual source alpha is zero (by setting + // the factors to zero). So let's do that. + if (CanReplaceAlphaWithStencil()) { + // Let the fragment shader take care of it. + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ZERO); + } else if (gstate.isStencilTestEnabled()) { + switch (ReplaceAlphaWithStencilType()) { + case STENCIL_VALUE_KEEP: + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ONE); + break; + case STENCIL_VALUE_ONE: + // This won't give one but it's our best shot... + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ONE); + break; + case STENCIL_VALUE_ZERO: + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ZERO); + break; + case STENCIL_VALUE_UNIFORM: + // This won't give a correct value (it multiplies) but it may be better than random values. + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_CONSTANT_ALPHA, GL_ZERO); + break; + case STENCIL_VALUE_UNKNOWN: + // For now, let's err at zero. This is INVERT or INCR/DECR. + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ZERO); + break; + } } else { - glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, glBlendFuncA, glBlendFuncB); + // Retain the existing value when stencil testing is off. + glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ONE); } // Don't report on Android device (why?) @@ -277,18 +325,17 @@ void TransformDrawEngine::ApplyDrawState(int prim) { glstate.dither.disable(); if (gstate.isModeClear()) { - #if !defined(USING_GLES2) // Logic Ops glstate.colorLogicOp.disable(); #endif - // Culling + // Culling glstate.cullFace.disable(); - + // Depth Test glstate.depthTest.enable(); glstate.depthFunc.set(GL_ALWAYS); - glstate.depthWrite.set(gstate.isClearModeDepthWriteEnabled() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); + glstate.depthWrite.set(gstate.isClearModeDepthMask() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); // Color Test bool colorMask = gstate.isClearModeColorMask(); @@ -341,6 +388,17 @@ void TransformDrawEngine::ApplyDrawState(int prim) { bool gmask = ((gstate.pmskc >> 8) & 0xFF) < 128; bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128; bool amask = (gstate.pmska & 0xFF) < 128; + + // Let's not write to alpha if stencil isn't enabled. + if (!gstate.isStencilTestEnabled()) { + amask = false; + } else { + // If the stencil type is set to KEEP, we shouldn't write to the stencil/alpha channel. + if (ReplaceAlphaWithStencilType() == STENCIL_VALUE_KEEP) { + amask = false; + } + } + glstate.colorMask.set(rmask, gmask, bmask, amask); // Stencil Test @@ -352,9 +410,9 @@ void TransformDrawEngine::ApplyDrawState(int prim) { glstate.stencilOp.set(stencilOps[gstate.getStencilOpSFail()], // stencil fail stencilOps[gstate.getStencilOpZFail()], // depth fail stencilOps[gstate.getStencilOpZPass()]); // depth pass - } else + } else { glstate.stencilTest.disable(); - + } } float renderWidthFactor, renderHeightFactor; @@ -372,7 +430,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) { float pixelH = PSP_CoreParameter().pixelHeight; CenterRect(&renderX, &renderY, &renderWidth, &renderHeight, 480, 272, pixelW, pixelH); } - + renderWidthFactor = (float)renderWidth / framebufferManager_->GetTargetWidth(); renderHeightFactor = (float)renderHeight / framebufferManager_->GetTargetHeight(); diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 8edb791a22..5e7efa505b 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -501,7 +501,7 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) { } } - if ((g_Config.iTexFiltering == LINEAR || (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos)) && !gstate.isColorTestEnabled() && !gstate.isAlphaTestEnabled()) { + if ((g_Config.iTexFiltering == LINEAR && !gstate.isColorTestEnabled() && !gstate.isAlphaTestEnabled()) || (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos)) { magFilt |= 1; minFilt |= 1; } @@ -703,10 +703,24 @@ inline bool TextureCache::TexCacheEntry::Matches(u16 dim2, u8 format2, int maxLe void TextureCache::LoadClut() { u32 clutAddr = gstate.getClutAddress(); - clutTotalBytes_ = gstate.getClutLoadBytes(); if (Memory::IsValidAddress(clutAddr)) { +#ifdef _M_SSE + int numBlocks = gstate.getClutLoadBlocks(); + clutTotalBytes_ = numBlocks * 32; + const __m128i *source = (const __m128i *)Memory::GetPointerUnchecked(clutAddr); + __m128i *dest = (__m128i *)clutBufRaw_; + for (int i = 0; i < numBlocks; i++, source += 2, dest += 2) { + __m128i data1 = _mm_loadu_si128(source); + __m128i data2 = _mm_loadu_si128(source + 1); + _mm_store_si128(dest, data1); + _mm_store_si128(dest + 1, data2); + } +#else + clutTotalBytes_ = gstate.getClutLoadBytes(); Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, clutTotalBytes_); +#endif } else { + clutTotalBytes_ = gstate.getClutLoadBytes(); memset(clutBufRaw_, 0xFF, clutTotalBytes_); } // Reload the clut next time. @@ -1207,7 +1221,7 @@ void *TextureCache::DecodeTextureLevel(GETextureFormat format, GEPaletteFormat c switch (format) { case GE_TFMT_CLUT4: { - const bool mipmapShareClut = (gstate.texmode & 0x100) == 0; + const bool mipmapShareClut = gstate.isClutSharedForMipmaps(); const int clutSharingOffset = mipmapShareClut ? 0 : level * 16; switch (clutformat) { diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index c70f0add84..b3de237982 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - - // Ideas for speeding things up on mobile OpenGL ES implementations // // Use superbuffers! Yes I just invented that name. @@ -81,21 +79,26 @@ #include "GPU/GPUState.h" #include "GPU/ge_constants.h" +#include "GPU/Common/SplineCommon.h" #include "GPU/GLES/StateMapping.h" #include "GPU/GLES/TextureCache.h" #include "GPU/GLES/TransformPipeline.h" #include "GPU/GLES/VertexDecoder.h" #include "GPU/GLES/ShaderManager.h" #include "GPU/GLES/GLES_GPU.h" +#include "GPU/Common/SplineCommon.h" -const GLuint glprim[8] = { +extern const GLuint glprim[8] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, - GL_TRIANGLES, // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? + GL_TRIANGLES, + // With OpenGL ES we have to expand sprites (rects) into triangles, tripling the data instead of doubling. + // Sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? + // We can use it on the desktop though, but we don't yet. There we could also use geometry shaders anyway. }; enum { @@ -109,11 +112,6 @@ enum { #define VERTEXCACHE_DECIMATION_INTERVAL 17 -// Check for max first as clamping to max is more common than min when lighting. -inline float clamp(float in, float min, float max) { - return in > max ? max : (in < min ? min : in); -} - TransformDrawEngine::TransformDrawEngine() : collectedVerts(0), prevPrim_(GE_PRIM_INVALID), @@ -125,7 +123,8 @@ TransformDrawEngine::TransformDrawEngine() framebufferManager_(0), numDrawCalls(0), vertexCountInDrawCalls(0), - uvScale(0) { + uvScale(0), + decodeCounter_(0) { decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; // Allocate nicely aligned memory. Maybe graphics drivers will // appreciate it. @@ -199,156 +198,6 @@ void TransformDrawEngine::GLLost() { InitDeviceObjects(); } -// Convenient way to do precomputation to save the parts of the lighting calculation -// that's common between the many vertices of a draw call. -class Lighter { -public: - Lighter(); - void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f normal); - -private: - Color4 globalAmbient; - Color4 materialEmissive; - Color4 materialAmbient; - Color4 materialDiffuse; - Color4 materialSpecular; - float specCoef_; - // Vec3f viewer_; - bool doShadeMapping_; - int materialUpdate_; -}; - -Lighter::Lighter() { - doShadeMapping_ = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP; - materialEmissive.GetFromRGB(gstate.materialemissive); - materialEmissive.a = 0.0f; - globalAmbient.GetFromRGB(gstate.ambientcolor); - globalAmbient.GetFromA(gstate.ambientalpha); - materialAmbient.GetFromRGB(gstate.materialambient); - materialAmbient.GetFromA(gstate.materialalpha); - materialDiffuse.GetFromRGB(gstate.materialdiffuse); - materialDiffuse.a = 1.0f; - materialSpecular.GetFromRGB(gstate.materialspecular); - materialSpecular.a = 1.0f; - specCoef_ = getFloat24(gstate.materialspecularcoef); - // viewer_ = Vec3f(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); - materialUpdate_ = gstate.materialupdate & 7; -} - -void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f norm) -{ - Color4 in(colorIn); - - const Color4 *ambient; - if (materialUpdate_ & 1) - ambient = ∈ - else - ambient = &materialAmbient; - - const Color4 *diffuse; - if (materialUpdate_ & 2) - diffuse = ∈ - else - diffuse = &materialDiffuse; - - const Color4 *specular; - if (materialUpdate_ & 4) - specular = ∈ - else - specular = &materialSpecular; - - Color4 lightSum0 = globalAmbient * *ambient + materialEmissive; - Color4 lightSum1(0, 0, 0, 0); - - for (int l = 0; l < 4; l++) - { - // can we skip this light? - if (!gstate.isLightChanEnabled(l)) - continue; - - GELightType type = gstate.getLightType(l); - - Vec3f toLight(0,0,0); - Vec3f lightDir(0,0,0); - - if (type == GE_LIGHTTYPE_DIRECTIONAL) - toLight = Vec3f(gstate_c.lightpos[l]); // lightdir is for spotlights - else - toLight = Vec3f(gstate_c.lightpos[l]) - pos; - - bool doSpecular = gstate.isUsingSpecularLight(l); - bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l); - - float distanceToLight = toLight.Length(); - float dot = 0.0f; - float angle = 0.0f; - float lightScale = 0.0f; - - if (distanceToLight > 0.0f) { - toLight /= distanceToLight; - dot = Dot(toLight, norm); - } - // Clamp dot to zero. - if (dot < 0.0f) dot = 0.0f; - - if (poweredDiffuse) - dot = powf(dot, specCoef_); - - // Attenuation - switch (type) { - case GE_LIGHTTYPE_DIRECTIONAL: - lightScale = 1.0f; - break; - case GE_LIGHTTYPE_POINT: - lightScale = clamp(1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight), 0.0f, 1.0f); - break; - case GE_LIGHTTYPE_SPOT: - case GE_LIGHTTYPE_UNKNOWN: - lightDir = gstate_c.lightdir[l]; - angle = Dot(toLight.Normalized(), lightDir.Normalized()); - if (angle >= gstate_c.lightangle[l]) - lightScale = clamp(1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, gstate_c.lightspotCoef[l]); - break; - default: - // ILLEGAL - break; - } - - Color4 lightDiff(gstate_c.lightColor[1][l], 0.0f); - Color4 diff = (lightDiff * *diffuse) * dot; - - // Real PSP specular - Vec3f toViewer(0,0,1); - // Better specular - // Vec3f toViewer = (viewer - pos).Normalized(); - - if (doSpecular) - { - Vec3f halfVec = (toLight + toViewer); - halfVec.Normalize(); - - dot = Dot(halfVec, norm); - if (dot > 0.0f) - { - Color4 lightSpec(gstate_c.lightColor[2][l], 0.0f); - lightSum1 += (lightSpec * *specular * (powf(dot, specCoef_) * lightScale)); - } - } - - if (gstate.isLightChanEnabled(l)) - { - Color4 lightAmbient(gstate_c.lightColor[0][l], 0.0f); - lightSum0 += (lightAmbient * *ambient + diff) * lightScale; - } - } - - // 4? - for (int i = 0; i < 4; i++) { - colorOut0[i] = lightSum0[i] > 1.0f ? 1.0f : lightSum0[i]; - colorOut1[i] = lightSum1[i] > 1.0f ? 1.0f : lightSum1[i]; - } -} - struct GlTypeInfo { u16 type; u8 count; @@ -393,499 +242,6 @@ static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff); } -// The verts are in the order: BR BL TL TR -static void SwapUVs(TransformedVertex &a, TransformedVertex &b) { - float tempu = a.u; - float tempv = a.v; - a.u = b.u; - a.v = b.v; - b.u = tempu; - b.v = tempv; -} - -// 2 3 3 2 0 3 2 1 -// to to or -// 1 0 0 1 1 2 3 0 - - -// See comment below where this was called before. -/* -static void RotateUV(TransformedVertex v[4]) { - float x1 = v[2].x; - float x2 = v[0].x; - float y1 = v[2].y; - float y2 = v[0].y; - - if ((x1 < x2 && y1 < y2) || (x1 > x2 && y1 > y2)) - SwapUVs(v[1], v[3]); -}*/ - -static void RotateUVThrough(TransformedVertex v[4]) { - float x1 = v[2].x; - float x2 = v[0].x; - float y1 = v[2].y; - float y2 = v[0].y; - - if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) - SwapUVs(v[1], v[3]); -} - -// Clears on the PSP are best done by drawing a series of vertical strips -// in clear mode. This tries to detect that. -bool TransformDrawEngine::IsReallyAClear(int numVerts) const { - if (transformed[0].x != 0.0f || transformed[0].y != 0.0f) - return false; - - u32 matchcolor; - memcpy(&matchcolor, transformed[0].color0, 4); - float matchz = transformed[0].z; - - int bufW = gstate_c.curRTWidth; - int bufH = gstate_c.curRTHeight; - - float prevX = 0.0f; - for (int i = 1; i < numVerts; i++) { - u32 vcolor; - memcpy(&vcolor, transformed[i].color0, 4); - if (vcolor != matchcolor || transformed[i].z != matchz) - return false; - - if ((i & 1) == 0) { - // Top left of a rectangle - if (transformed[i].y != 0) - return false; - if (i > 0 && transformed[i].x != transformed[i - 1].x) - return false; - } else { - // Bottom right - if (transformed[i].y != bufH) - return false; - if (transformed[i].x <= transformed[i - 1].x) - return false; - } - } - - // The last vertical strip often extends outside the drawing area. - if (transformed[numVerts - 1].x < bufW) - return false; - - return true; -} - -// This is the software transform pipeline, which is necessary for supporting RECT -// primitives correctly, and may be easier to use for debugging than the hardware -// transform pipeline. - -// There's code here that simply expands transformed RECTANGLES into plain triangles. - -// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0. -// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of -// this code. - -// Actually, if we find the camera-relative right and down vectors, it might even be possible to add the extra points in pre-transformed -// space and thus make decent use of hardware transform. - -// Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for -// GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. -void TransformDrawEngine::SoftwareTransformAndDraw( - int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { - - bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; - bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled(); - - // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. - -#if defined(USING_GLES2) - if (vertexCount > 0x10000/3) - vertexCount = 0x10000/3; -#endif - - float uscale = 1.0f; - float vscale = 1.0f; - if (throughmode) { - uscale /= gstate_c.curTextureWidth; - vscale /= gstate_c.curTextureHeight; - } - - bool scaleUV = !g_Config.bPrescaleUV; - - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - float widthFactor = (float) w / (float) gstate_c.curTextureWidth; - float heightFactor = (float) h / (float) gstate_c.curTextureHeight; - - Lighter lighter; - float fog_end = getFloat24(gstate.fog1); - float fog_slope = getFloat24(gstate.fog2); - - VertexReader reader(decoded, decVtxFormat, vertType); - for (int index = 0; index < maxIndex; index++) { - reader.Goto(index); - - float v[3] = {0, 0, 0}; - float c0[4] = {1, 1, 1, 1}; - float c1[4] = {0, 0, 0, 0}; - float uv[3] = {0, 0, 1}; - float fogCoef = 1.0f; - - if (throughmode) { - // Do not touch the coordinates or the colors. No lighting. - reader.ReadPos(v); - if (reader.hasColor0()) { - reader.ReadColor0(c0); - for (int j = 0; j < 4; j++) { - c1[j] = 0.0f; - } - } else { - c0[0] = gstate.getMaterialAmbientR() / 255.f; - c0[1] = gstate.getMaterialAmbientG() / 255.f; - c0[2] = gstate.getMaterialAmbientB() / 255.f; - c0[3] = gstate.getMaterialAmbientA() / 255.f; - } - - if (reader.hasUV()) { - reader.ReadUV(uv); - - uv[0] *= uscale; - uv[1] *= vscale; - } - fogCoef = 1.0f; - // Scale UV? - } else { - // We do software T&L for now - float out[3], norm[3]; - float pos[3], nrm[3]; - Vec3f normal(0, 0, 1); - reader.ReadPos(pos); - if (reader.hasNormal()) - reader.ReadNrm(nrm); - - if (!vertTypeIsSkinningEnabled(vertType)) { - Vec3ByMatrix43(out, pos, gstate.worldMatrix); - if (reader.hasNormal()) { - Norm3ByMatrix43(norm, nrm, gstate.worldMatrix); - normal = Vec3f(norm).Normalized(); - } - } else { - float weights[8]; - reader.ReadWeights(weights); - // Skinning - Vec3f psum(0,0,0); - Vec3f nsum(0,0,0); - for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) { - if (weights[i] != 0.0f) { - Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12); - Vec3f tpos(out); - psum += tpos * weights[i]; - if (reader.hasNormal()) { - Norm3ByMatrix43(norm, nrm, gstate.boneMatrix+i*12); - Vec3f tnorm(norm); - nsum += tnorm * weights[i]; - } - } - } - - // Yes, we really must multiply by the world matrix too. - Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix); - if (reader.hasNormal()) { - Norm3ByMatrix43(norm, nsum.AsArray(), gstate.worldMatrix); - normal = Vec3f(norm).Normalized(); - } - } - - // Perform lighting here if enabled. don't need to check through, it's checked above. - float unlitColor[4] = {1, 1, 1, 1}; - if (reader.hasColor0()) { - reader.ReadColor0(unlitColor); - } else { - unlitColor[0] = gstate.getMaterialAmbientR() / 255.f; - unlitColor[1] = gstate.getMaterialAmbientG() / 255.f; - unlitColor[2] = gstate.getMaterialAmbientB() / 255.f; - unlitColor[3] = gstate.getMaterialAmbientA() / 255.f; - } - float litColor0[4]; - float litColor1[4]; - lighter.Light(litColor0, litColor1, unlitColor, out, normal); - - if (gstate.isLightingEnabled()) { - // Don't ignore gstate.lmode - we should send two colors in that case - for (int j = 0; j < 4; j++) { - c0[j] = litColor0[j]; - } - if (lmode) { - // Separate colors - for (int j = 0; j < 4; j++) { - c1[j] = litColor1[j]; - } - } else { - // Summed color into c0 - for (int j = 0; j < 4; j++) { - c0[j] = ((c0[j] + litColor1[j]) > 1.0f) ? 1.0f : (c0[j] + litColor1[j]); - } - } - } else { - if (reader.hasColor0()) { - for (int j = 0; j < 4; j++) { - c0[j] = unlitColor[j]; - } - } else { - c0[0] = gstate.getMaterialAmbientR() / 255.f; - c0[1] = gstate.getMaterialAmbientG() / 255.f; - c0[2] = gstate.getMaterialAmbientB() / 255.f; - c0[3] = gstate.getMaterialAmbientA() / 255.f; - } - if (lmode) { - for (int j = 0; j < 4; j++) { - c1[j] = 0.0f; - } - } - } - - float ruv[2] = {0.0f, 0.0f}; - if (reader.hasUV()) - reader.ReadUV(ruv); - - // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. - switch (gstate.getUVGenMode()) { - case GE_TEXMAP_TEXTURE_COORDS: // UV mapping - case GE_TEXMAP_UNKNOWN: // Seen in Riviera. Unsure of meaning, but this works. - // Texture scale/offset is only performed in this mode. - if (scaleUV) { - uv[0] = uscale * (ruv[0]*gstate_c.uv.uScale + gstate_c.uv.uOff); - uv[1] = vscale * (ruv[1]*gstate_c.uv.vScale + gstate_c.uv.vOff); - } else { - uv[0] = uscale * ruv[0]; - uv[1] = vscale * ruv[1]; - } - uv[2] = 1.0f; - break; - - case GE_TEXMAP_TEXTURE_MATRIX: - { - // Projection mapping - Vec3f source; - switch (gstate.getUVProjMode()) { - case GE_PROJMAP_POSITION: // Use model space XYZ as source - source = pos; - break; - - case GE_PROJMAP_UV: // Use unscaled UV as source - source = Vec3f(ruv[0], ruv[1], 0.0f); - break; - - case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source - if (reader.hasNormal()) { - source = Vec3f(norm).Normalized(); - } else { - ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?"); - source = Vec3f(0.0f, 0.0f, 1.0f); - } - break; - - case GE_PROJMAP_NORMAL: // Use non-normalized normal as source! - if (reader.hasNormal()) { - source = Vec3f(norm); - } else { - ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?"); - source = Vec3f(0.0f, 0.0f, 1.0f); - } - break; - } - - float uvw[3]; - Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix); - uv[0] = uvw[0]; - uv[1] = uvw[1]; - uv[2] = uvw[2]; - } - break; - - case GE_TEXMAP_ENVIRONMENT_MAP: - // Shade mapping - use two light sources to generate U and V. - { - Vec3f lightpos0 = Vec3f(gstate_c.lightpos[gstate.getUVLS0()]).Normalized(); - Vec3f lightpos1 = Vec3f(gstate_c.lightpos[gstate.getUVLS1()]).Normalized(); - - uv[0] = (1.0f + Dot(lightpos0, normal))/2.0f; - uv[1] = (1.0f - Dot(lightpos1, normal))/2.0f; - uv[2] = 1.0f; - } - break; - - default: - // Illegal - ERROR_LOG_REPORT(G3D, "Impossible UV gen mode? %d", gstate.getUVGenMode()); - break; - } - - uv[0] = uv[0] * widthFactor; - uv[1] = uv[1] * heightFactor; - - // Transform the coord by the view matrix. - Vec3ByMatrix43(v, out, gstate.viewMatrix); - fogCoef = (v[2] + fog_end) * fog_slope; - } - - // TODO: Write to a flexible buffer, we don't always need all four components. - memcpy(&transformed[index].x, v, 3 * sizeof(float)); - transformed[index].fog = fogCoef; - memcpy(&transformed[index].u, uv, 3 * sizeof(float)); - if (gstate_c.flipTexture) { - transformed[index].v = 1.0f - transformed[index].v; - } - for (int i = 0; i < 4; i++) { - transformed[index].color0[i] = c0[i] * 255.0f; - } - for (int i = 0; i < 3; i++) { - transformed[index].color1[i] = c1[i] * 255.0f; - } - } - - // Here's the best opportunity to try to detect rectangles used to clear the screen, and - // replace them with real OpenGL clears. This can provide a speedup on certain mobile chips. - // Disabled for now - depth does not come out exactly the same. - // - // An alternative option is to simply ditch all the verts except the first and last to create a single - // rectangle out of many. Quite a small optimization though. - if (false && maxIndex > 1 && gstate.isModeClear() && prim == GE_PRIM_RECTANGLES && IsReallyAClear(maxIndex)) { - u32 clearColor; - memcpy(&clearColor, transformed[0].color0, 4); - float clearDepth = transformed[0].z; - const float col[4] = { - ((clearColor & 0xFF)) / 255.0f, - ((clearColor & 0xFF00) >> 8) / 255.0f, - ((clearColor & 0xFF0000) >> 16) / 255.0f, - ((clearColor & 0xFF000000) >> 24) / 255.0f, - }; - - bool colorMask = gstate.isClearModeColorMask(); - bool alphaMask = gstate.isClearModeAlphaMask(); - glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask); - if (alphaMask) { - glstate.stencilTest.set(true); - // Clear stencil - // TODO: extract the stencilValue properly, see below - int stencilValue = 0; - glstate.stencilFunc.set(GL_ALWAYS, stencilValue, 255); - } else { - // Don't touch stencil - glstate.stencilTest.set(false); - } - glstate.scissorTest.set(false); - bool depthMask = gstate.isClearModeDepthMask(); - - int target = 0; - if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - - glClearColor(col[0], col[1], col[2], col[3]); -#ifdef USING_GLES2 - glClearDepthf(clearDepth); -#else - glClearDepth(clearDepth); -#endif - glClearStencil(0); // TODO - take from alpha? - glClear(target); - return; - } - - // Step 2: expand rectangles. - const TransformedVertex *drawBuffer = transformed; - int numTrans = 0; - - bool drawIndexed = false; - - if (prim != GE_PRIM_RECTANGLES) { - // We can simply draw the unexpanded buffer. - numTrans = vertexCount; - drawIndexed = true; - } else { - numTrans = 0; - drawBuffer = transformedExpanded; - TransformedVertex *trans = &transformedExpanded[0]; - TransformedVertex saved; - u32 stencilValue; - for (int i = 0; i < vertexCount; i += 2) { - int index = ((const u16*)inds)[i]; - saved = transformed[index]; - int index2 = ((const u16*)inds)[i + 1]; - TransformedVertex &transVtx = transformed[index2]; - if (i == 0) - stencilValue = transVtx.color0[3]; - // We have to turn the rectangle into two triangles, so 6 points. Sigh. - - // bottom right - trans[0] = transVtx; - - // bottom left - trans[1] = transVtx; - trans[1].y = saved.y; - trans[1].v = saved.v; - - // top left - trans[2] = transVtx; - trans[2].x = saved.x; - trans[2].y = saved.y; - trans[2].u = saved.u; - trans[2].v = saved.v; - - // top right - trans[3] = transVtx; - trans[3].x = saved.x; - trans[3].u = saved.u; - - // That's the four corners. Now process UV rotation. - if (throughmode) - RotateUVThrough(trans); - - // Apparently, non-through RotateUV just breaks things. - // If we find a game where it helps, we'll just have to figure out how they differ. - // Possibly, it has something to do with flipped viewport Y axis, which a few games use. - // One game might be one of the Metal Gear ones, can't find the issue right now though. - // else - // RotateUV(trans); - - // bottom right - trans[4] = trans[0]; - - // top left - trans[5] = trans[2]; - trans += 6; - - numTrans += 6; - } - - // We don't know the color until here, so we have to do it now, instead of in StateMapping. - // Might want to reconsider the order of things later... - if (gstate.isModeClear() && gstate.isClearModeAlphaMask()) { - glstate.stencilFunc.set(GL_ALWAYS, stencilValue, 255); - } - } - - // TODO: Add a post-transform cache here for multi-RECTANGLES only. - // Might help for text drawing. - - // these spam the gDebugger log. - const int vertexSize = sizeof(transformed[0]); - - bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX; - glBindBuffer(GL_ARRAY_BUFFER, 0); - glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); - int attrMask = program->attrMask; - if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4); - if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4); - if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 8 * 4); - if (drawIndexed) { -#ifdef USING_GLES2 - glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds); -#else - glDrawRangeElements(glprim[prim], 0, indexGen.MaxIndex(), numTrans, GL_UNSIGNED_SHORT, inds); -#endif - } else { - glDrawArrays(glprim[prim], 0, numTrans); - } -} - VertexDecoder *TransformDrawEngine::GetVertexDecoder(u32 vtype) { auto iter = decoderMap_.find(vtype); if (iter != decoderMap_.end()) @@ -897,11 +253,15 @@ VertexDecoder *TransformDrawEngine::GetVertexDecoder(u32 vtype) { } void TransformDrawEngine::SetupVertexDecoder(u32 vertType) { + // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it + // into the top of the verttype where there are unused bits. + u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); + // If vtype has changed, setup the vertex decoder. // TODO: Simply cache the setup decoders instead. - if (vertType != lastVType_) { - dec_ = GetVertexDecoder(vertType); - lastVType_ = vertType; + if (vertTypeID != lastVType_) { + dec_ = GetVertexDecoder(vertTypeID); + lastVType_ = vertTypeID; } } @@ -933,7 +293,7 @@ int TransformDrawEngine::EstimatePerVertexCost() { return cost; } -void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int forceIndexType, int *bytesRead) { +void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) { if (vertexCount == 0) return; // we ignore zero-sized draw calls. @@ -960,7 +320,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr dc.verts = verts; dc.inds = inds; dc.vertType = vertType; - dc.indexType = ((forceIndexType == -1) ? (vertType & GE_VTYPE_IDX_MASK) : forceIndexType) >> GE_VTYPE_IDX_SHIFT; + dc.indexType = (vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; dc.prim = prim; dc.vertexCount = vertexCount; if (inds) { @@ -973,78 +333,25 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr if (uvScale) { uvScale[numDrawCalls] = gstate_c.uv; } + numDrawCalls++; vertexCountInDrawCalls += vertexCount; + + if (g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK)) { + DecodeVertsStep(); + decodeCounter_++; + } } void TransformDrawEngine::DecodeVerts() { UVScale origUV; if (uvScale) origUV = gstate_c.uv; - for (int i = 0; i < numDrawCalls; i++) { - const DeferredDrawCall &dc = drawCalls[i]; - - indexGen.SetIndex(collectedVerts); - int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound; - - u32 indexType = dc.indexType; - void *inds = dc.inds; - if (indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) { - // Decode the verts and apply morphing. Simple. - if (uvScale) - gstate_c.uv = uvScale[i]; - dec_->DecodeVerts(decoded + collectedVerts * (int)dec_->GetDecVtxFmt().stride, - dc.verts, indexLowerBound, indexUpperBound); - collectedVerts += indexUpperBound - indexLowerBound + 1; - indexGen.AddPrim(dc.prim, dc.vertexCount); - } else { - // It's fairly common that games issue long sequences of PRIM calls, with differing - // inds pointer but the same base vertex pointer. We'd like to reuse vertices between - // these as much as possible, so we make sure here to combine as many as possible - // into one nice big drawcall, sharing data. - - // 1. Look ahead to find the max index, only looking as "matching" drawcalls. - // Expand the lower and upper bounds as we go. - int j = i + 1; - int lastMatch = i; - while (j < numDrawCalls) { - if (drawCalls[j].verts != dc.verts) - break; - if (uvScale && memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0) - break; - - indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); - indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); - lastMatch = j; - j++; - } - - // 2. Loop through the drawcalls, translating indices as we go. - for (j = i; j <= lastMatch; j++) { - switch (indexType) { - case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound); - break; - case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound); - break; - } - } - - int vertexCount = indexUpperBound - indexLowerBound + 1; - // 3. Decode that range of vertex data. - if (uvScale) - gstate_c.uv = uvScale[i]; - dec_->DecodeVerts(decoded + collectedVerts * (int)dec_->GetDecVtxFmt().stride, - dc.verts, indexLowerBound, indexUpperBound); - collectedVerts += vertexCount; - - // 4. Advance indexgen vertex counter. - indexGen.Advance(vertexCount); - i = lastMatch; - } + for (; decodeCounter_ < numDrawCalls; decodeCounter_++) { + if (uvScale) + gstate_c.uv = uvScale[decodeCounter_]; + DecodeVertsStep(); } - // Sanity check if (indexGen.Prim() < 0) { ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim()); @@ -1055,6 +362,68 @@ void TransformDrawEngine::DecodeVerts() { gstate_c.uv = origUV; } +void TransformDrawEngine::DecodeVertsStep() { + const int i = decodeCounter_; + + const DeferredDrawCall &dc = drawCalls[i]; + + indexGen.SetIndex(collectedVerts); + int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound; + + u32 indexType = dc.indexType; + void *inds = dc.inds; + if (indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) { + // Decode the verts and apply morphing. Simple. + dec_->DecodeVerts(decoded + collectedVerts * (int)dec_->GetDecVtxFmt().stride, + dc.verts, indexLowerBound, indexUpperBound); + collectedVerts += indexUpperBound - indexLowerBound + 1; + indexGen.AddPrim(dc.prim, dc.vertexCount); + } else { + // It's fairly common that games issue long sequences of PRIM calls, with differing + // inds pointer but the same base vertex pointer. We'd like to reuse vertices between + // these as much as possible, so we make sure here to combine as many as possible + // into one nice big drawcall, sharing data. + + // 1. Look ahead to find the max index, only looking as "matching" drawcalls. + // Expand the lower and upper bounds as we go. + int j = i + 1; + int lastMatch = i; + while (j < numDrawCalls) { + if (drawCalls[j].verts != dc.verts) + break; + if (uvScale && memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0) + break; + + indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); + lastMatch = j; + j++; + } + + // 2. Loop through the drawcalls, translating indices as we go. + for (j = i; j <= lastMatch; j++) { + switch (indexType) { + case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound); + break; + case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound); + break; + } + } + + int vertexCount = indexUpperBound - indexLowerBound + 1; + // 3. Decode that range of vertex data. + dec_->DecodeVerts(decoded + collectedVerts * (int)dec_->GetDecVtxFmt().stride, + dc.verts, indexLowerBound, indexUpperBound); + collectedVerts += vertexCount; + + // 4. Advance indexgen vertex counter. + indexGen.Advance(vertexCount); + decodeCounter_ = lastMatch; + } +} + u32 TransformDrawEngine::ComputeHash() { u32 fullhash = 0; int vertexSize = dec_->GetDecVtxFmt().stride; @@ -1131,21 +500,10 @@ void TransformDrawEngine::DecimateTrackedVertexArrays() { if (iter->second->lastFrame < threshold) { delete iter->second; vai_.erase(iter++); - } - else + } else { ++iter; + } } - - // Enable if you want to see vertex decoders in the log output. Need a better way. -#if 0 - char buffer[16384]; - for (std::map::iterator dec = decoderMap_.begin(); dec != decoderMap_.end(); ++dec) { - char *ptr = buffer; - ptr += dec->second->ToString(ptr); -// *ptr++ = '\n'; - NOTICE_LOG(G3D, buffer); - } -#endif } VertexArrayInfo::~VertexArrayInfo() { @@ -1157,7 +515,6 @@ VertexArrayInfo::~VertexArrayInfo() { void TransformDrawEngine::DoFlush() { gpuStats.numFlushes++; - gpuStats.numTrackedVertexArrays = (int)vai_.size(); // This is not done on every drawcall, we should collect vertex data @@ -1168,13 +525,21 @@ void TransformDrawEngine::DoFlush() { LinkedShader *program = shaderManager_->ApplyShader(prim, lastVType_); + // Compiler warns about this because it's only used in the #ifdeffed out RangeElements path. + int maxIndex = 0; + if (program->useHWTransform_) { GLuint vbo = 0, ebo = 0; int vertexCount = 0; - int maxIndex = 0; bool useElements = true; + // Cannot cache vertex data with morph enabled. - if (g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK)) { + bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); + // Also avoid caching when software skinning. + if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + useCache = false; + + if (useCache) { u32 id = ComputeFastDCID(); auto iter = vai_.find(id); VertexArrayInfo *vai; @@ -1249,7 +614,7 @@ void TransformDrawEngine::DoFlush() { if (!useElements && indexGen.PureCount()) { vai->numVerts = indexGen.PureCount(); } - + glGenBuffers(1, &vai->vbo); glBindBuffer(GL_ARRAY_BUFFER, vai->vbo); glBufferData(GL_ARRAY_BUFFER, dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(), decoded, GL_STATIC_DRAW); @@ -1314,6 +679,7 @@ void TransformDrawEngine::DoFlush() { vai->lastFrame = gpuStats.numFlips; } else { DecodeVerts(); + rotateVBO: gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); useElements = !indexGen.SeenOnlyPurePrims(); @@ -1327,12 +693,12 @@ rotateVBO: prim = indexGen.Prim(); } - - DEBUG_LOG(G3D, "Flush prim %i! %i verts in one go", prim, vertexCount); + + VERBOSE_LOG(G3D, "Flush prim %i! %i verts in one go", prim, vertexCount); SetupDecFmtForDraw(program, dec_->GetDecVtxFmt(), vbo ? 0 : decoded); if (useElements) { -#ifdef USING_GLES2 +#if 1 // USING_GLES2 glDrawElements(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, ebo ? 0 : (GLvoid*)decIndex); #else glDrawRangeElements(glprim[prim], 0, maxIndex, vertexCount, GL_UNSIGNED_SHORT, ebo ? 0 : (GLvoid*)decIndex); @@ -1351,10 +717,9 @@ rotateVBO: // Undo the strip optimization, not supported by the SW code yet. if (prim == GE_PRIM_TRIANGLE_STRIP) prim = GE_PRIM_TRIANGLES; - DEBUG_LOG(G3D, "Flush prim %i SW! %i verts in one go", prim, indexGen.VertexCount()); SoftwareTransformAndDraw( - prim, decoded, program, indexGen.VertexCount(), + prim, decoded, program, indexGen.VertexCount(), dec_->VertexType(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(), indexGen.MaxIndex()); } @@ -1363,6 +728,7 @@ rotateVBO: collectedVerts = 0; numDrawCalls = 0; vertexCountInDrawCalls = 0; + decodeCounter_ = 0; prevPrim_ = GE_PRIM_INVALID; #ifndef USING_GLES2 @@ -1370,49 +736,216 @@ rotateVBO: #endif } +struct Plane { + float x, y, z, w; + void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } + float Test(float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; } +}; + +void PlanesFromMatrix(float mtx[16], Plane planes[6]) { + planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]); // Right + planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]); // Left + planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]); // Bottom + planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]); // Top + planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near + planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far +} + +static void ConvertMatrix4x3To4x4(float *m4x4, const float *m4x3) { + m4x4[0] = m4x3[0]; + m4x4[1] = m4x3[1]; + m4x4[2] = m4x3[2]; + m4x4[3] = 0.0f; + m4x4[4] = m4x3[3]; + m4x4[5] = m4x3[4]; + m4x4[6] = m4x3[5]; + m4x4[7] = 0.0f; + m4x4[8] = m4x3[6]; + m4x4[9] = m4x3[7]; + m4x4[10] = m4x3[8]; + m4x4[11] = 0.0f; + m4x4[12] = m4x3[9]; + m4x4[13] = m4x3[10]; + m4x4[14] = m4x3[11]; + m4x4[15] = 1.0f; +} + +// This code is HIGHLY unoptimized! +// +// It does the simplest and safest test possible: If all points of a bbox is outside a single of +// our clipping planes, we reject the box. bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) { - // Simplify away bones and morph before proceeding - - /* SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12); - u8 *temp_buffer = decoded + 65536 * 24; + float *verts = (float *)(decoded + 65536 * 18); - u32 origVertType = vertType; - vertType = NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType); - - for (int cube = 0; cube < vertexCount / 8; cube++) { - // For each cube... - - for (int i = 0; i < 8; i++) { - const SimpleVertex &vert = corners[cube * 8 + i]; - - // To world space... - float worldPos[3]; - Vec3ByMatrix43(worldPos, (float *)&vert.pos.x, gstate.worldMatrix); - - // To view space... - float viewPos[3]; - Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix); - - // And finally to screen space. - float frustumPos[4]; - Vec3ByMatrix44(frustumPos, viewPos, gstate.projMatrix); - - // Project to 2D - float x = frustumPos[0] / frustumPos[3]; - float y = frustumPos[1] / frustumPos[3]; - - // Rescale 2d position - // ... + // Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder + // and a large vertex format. + if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT) { + // memcpy(verts, control_points, 12 * vertexCount); + verts = (float *)control_points; + } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT) { + const s8 *vtx = (const s8 *)control_points; + for (int i = 0; i < vertexCount * 3; i++) { + verts[i] = vtx[i] * (1.0f / 128.0f); + } + } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT) { + const s16 *vtx = (const s16*)control_points; + for (int i = 0; i < vertexCount * 3; i++) { + verts[i] = vtx[i] * (1.0f / 32768.0f); + } + } else { + // Simplify away bones and morph before proceeding + u8 *temp_buffer = decoded + 65536 * 24; + NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType); + // Special case for float positions only. + const float *ctrl = (const float *)control_points; + for (int i = 0; i < vertexCount; i++) { + verts[i * 3] = corners[i].pos.x; + verts[i * 3 + 1] = corners[i].pos.y; + verts[i * 3 + 2] = corners[i].pos.z; + } + } + + Plane planes[6]; + + float world[16]; + float view[16]; + float worldview[16]; + float worldviewproj[16]; + ConvertMatrix4x3To4x4(world, gstate.worldMatrix); + ConvertMatrix4x3To4x4(view, gstate.viewMatrix); + Matrix4ByMatrix4(worldview, world, view); + Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix); + PlanesFromMatrix(worldviewproj, planes); + for (int plane = 0; plane < 6; plane++) { + int inside = 0; + int out = 0; + for (int i = 0; i < vertexCount; i++) { + // Here we can test against the frustum planes! + float value = planes[plane].Test(verts + i * 3); + if (value < 0) + out++; + else + inside++; + } + + if (inside == 0) { + // All out + return false; + } + + // Any out. For testing that the planes are in the right locations. + // if (out != 0) return false; + } + + return true; +} + +// TODO: Probably move this to common code (with normalization?) + +static inline Vec3f ClipToScreen(const Vec4f& coords) +{ + // TODO: Check for invalid parameters (x2 < x1, etc) + float vpx1 = getFloat24(gstate.viewportx1); + float vpx2 = getFloat24(gstate.viewportx2); + float vpy1 = getFloat24(gstate.viewporty1); + float vpy2 = getFloat24(gstate.viewporty2); + float vpz1 = getFloat24(gstate.viewportz1); + float vpz2 = getFloat24(gstate.viewportz2); + + float retx = coords.x * vpx1 / coords.w + vpx2; + float rety = coords.y * vpy1 / coords.w + vpy2; + float retz = coords.z * vpz1 / coords.w + vpz2; + + // 16 = 0xFFFF / 4095.9375 + return Vec3f(retx * 16, rety * 16, retz); +} + +static Vec3f ScreenToDrawing(const Vec3f& coords) +{ + Vec3f ret; + ret.x = coords.x - gstate.getOffsetX16(); + ret.y = coords.y - gstate.getOffsetY16(); + + // Convert from 16-bit fixed point to float. + ret.x *= 1.0 / 16.0; + ret.y *= 1.0 / 16.0; + ret.z = coords.z; + return ret; +} + +// TODO: This probably is not the best interface. +bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + // This is always for the current vertices. + u16 indexLowerBound = 0; + u16 indexUpperBound = count - 1; + + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + const u8 *inds = Memory::GetPointer(gstate_c.indexAddr); + const u16 *inds16 = (const u16 *)inds; + + if (inds) { + GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound); + indices.resize(count); + switch (gstate.vertType & GE_VTYPE_IDX_MASK) { + case GE_VTYPE_IDX_16BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds16[i]; + } + break; + case GE_VTYPE_IDX_8BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds[i]; + } + break; + default: + return false; + } + } else { + indices.clear(); + } + } else { + indices.clear(); + } + + static std::vector temp_buffer; + static std::vector simpleVertices; + temp_buffer.resize(65536 * 24 / sizeof(u32)); + simpleVertices.resize(indexUpperBound + 1); + NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType); + + float world[16]; + float view[16]; + float worldview[16]; + float worldviewproj[16]; + ConvertMatrix4x3To4x4(world, gstate.worldMatrix); + ConvertMatrix4x3To4x4(view, gstate.viewMatrix); + Matrix4ByMatrix4(worldview, world, view); + Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix); + + vertices.resize(indexUpperBound + 1); + for (int i = indexLowerBound; i <= indexUpperBound; ++i) { + const SimpleVertex &vert = simpleVertices[i]; + + if (gstate.isModeThrough()) { + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + vertices[i].x = vert.pos.x; + vertices[i].y = vert.pos.y; + vertices[i].z = vert.pos.z; + } else { + float clipPos[4]; + Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj); + Vec3f screenPos = ClipToScreen(clipPos); + Vec3f drawPos = ScreenToDrawing(screenPos); + + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + vertices[i].x = drawPos.x; + vertices[i].y = drawPos.y; + vertices[i].z = 1.0; } } - */ - - // Let's think. A better approach might be to take the edges of the drawing region and the projection - // matrix to build a frustum pyramid, and then clip the cube against those planes. If all vertices fail the same test, - // the cube is out. Otherwise it's in. - // TODO.... - return true; } diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 543a8a2f8c..7d463237dc 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -19,6 +19,7 @@ #include +#include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/IndexGenerator.h" #include "GPU/GLES/VertexDecoder.h" #include "gfx/gl_common.h" @@ -92,12 +93,13 @@ public: TransformDrawEngine(); virtual ~TransformDrawEngine(); - void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int forceIndexType, int *bytesRead); + void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead); void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType); void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType); bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType); - void DecodeVerts(); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); + void SetShaderManager(ShaderManager *shaderManager) { shaderManager_ = shaderManager; } @@ -126,7 +128,13 @@ public: DoFlush(); } + bool IsCodePtrVertexDecoder(const u8 *ptr) const { + return decJitCache_->IsInSpace(ptr); + } + private: + void DecodeVerts(); + void DecodeVertsStep(); void DoFlush(); void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertexType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); void ApplyDrawState(int prim); @@ -195,6 +203,7 @@ private: int vertexCountInDrawCalls; int decimationCounter_; + int decodeCounter_; UVScale *uvScale; }; diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 5d4ae09048..04f1cd316e 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -15,58 +15,32 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "math/lin/matrix4x4.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "Common/CPUDetect.h" #include "Core/Config.h" #include "Core/MemMap.h" #include "GPU/ge_constants.h" +#include "GPU/Math3D.h" #include "VertexDecoder.h" #include "VertexShaderGenerator.h" -extern void DisassembleArm(const u8 *data, int size); - static const u8 tcsize[4] = {0,2,4,8}, tcalign[4] = {0,1,2,4}; static const u8 colsize[8] = {0,0,0,0,2,2,2,4}, colalign[8] = {0,0,0,0,2,2,2,4}; static const u8 nrmsize[4] = {0,3,6,12}, nrmalign[4] = {0,1,2,4}; static const u8 possize[4] = {0,3,6,12}, posalign[4] = {0,1,2,4}; static const u8 wtsize[4] = {0,1,2,4}, wtalign[4] = {0,1,2,4}; +// When software skinning. This array is only used when non-jitted - when jitted, the matrix +// is kept in registers. +static float MEMORY_ALIGNED16(skinMatrix[12]); + inline int align(int n, int align) { return (n + (align - 1)) & ~(align - 1); } -#if 0 -// This is what the software transform spits out, and thus w -DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { - DecVtxFormat tfm = {0}; - int size = 0; - int offset = 0; - // Weights disappear during transform. - if (fmt.uvfmt) { - // UV always becomes float2. - tfm.uvfmt = DEC_FLOAT_2; - tfm.uvoff = offset; - offset += DecFmtSize(tfm.uvfmt); - } - // We always (?) get two colors out, they're floats (although we'd probably be fine with less precision). - tfm.c0fmt = DEC_FLOAT_4; - tfm.c0off = offset; - offset += DecFmtSize(tfm.c0fmt); - tfm.c1fmt = DEC_FLOAT_3; // color1 (specular) doesn't have alpha. - tfm.c1off = offset; - offset += DecFmtSize(tfm.c1fmt); - // We never get a normal, it's gone. - // But we do get a position, and it's always float3. - tfm.posfmt = DEC_FLOAT_3; - tfm.posoff = offset; - offset += DecFmtSize(tfm.posfmt); - // Update stride. - tfm.stride = offset; - return tfm; -} -#endif - VertexDecoder::VertexDecoder() : coloff(0), nrmoff(0), posoff(0), jitted_(0) { memset(stats_, 0, sizeof(stats_)); } @@ -108,6 +82,57 @@ void VertexDecoder::Step_WeightsFloat() const wt[j++] = 0.0f; } +void VertexDecoder::Step_WeightsU8Skin() const +{ + memset(skinMatrix, 0, sizeof(skinMatrix)); + u8 *wt = (u8 *)(decoded_ + decFmt.w0off); + const u8 *wdata = (const u8*)(ptr_); + for (int j = 0; j < nweights; j++) { + const float *bone = &gstate.boneMatrix[j * 12]; + if (wdata[j] != 0) { + float weight = wdata[j] / 128.0f; + for (int i = 0; i < 12; i++) { + skinMatrix[i] += weight * bone[i]; + } + } + } +} + +void VertexDecoder::Step_WeightsU16Skin() const +{ + memset(skinMatrix, 0, sizeof(skinMatrix)); + u16 *wt = (u16 *)(decoded_ + decFmt.w0off); + const u16 *wdata = (const u16*)(ptr_); + for (int j = 0; j < nweights; j++) { + const float *bone = &gstate.boneMatrix[j * 12]; + if (wdata[j] != 0) { + float weight = wdata[j] / 32768.0f; + for (int i = 0; i < 12; i++) { + skinMatrix[i] += weight * bone[i]; + } + } + } +} + +// Float weights should be uncommon, we can live with having to multiply these by 2.0 +// to avoid special checks in the vertex shader generator. +// (PSP uses 0.0-2.0 fixed point numbers for weights) +void VertexDecoder::Step_WeightsFloatSkin() const +{ + memset(skinMatrix, 0, sizeof(skinMatrix)); + float *wt = (float *)(decoded_ + decFmt.w0off); + const float *wdata = (const float*)(ptr_); + for (int j = 0; j < nweights; j++) { + const float *bone = &gstate.boneMatrix[j * 12]; + float weight = wdata[j]; + if (weight > 0.0) { + for (int i = 0; i < 12; i++) { + skinMatrix[i] += weight * bone[i]; + } + } + } +} + void VertexDecoder::Step_TcU8() const { // u32 to write two bytes of zeroes for free. @@ -314,6 +339,29 @@ void VertexDecoder::Step_NormalFloat() const normal[j] = fv[j]; } +void VertexDecoder::Step_NormalS8Skin() const +{ + float *normal = (float *)(decoded_ + decFmt.nrmoff); + const s8 *sv = (const s8*)(ptr_ + nrmoff); + const float fn[3] = { sv[0] / 128.0f, sv[1] / 128.0f, sv[2] / 128.0f }; + Norm3ByMatrix43(normal, fn, skinMatrix); +} + +void VertexDecoder::Step_NormalS16Skin() const +{ + float *normal = (float *)(decoded_ + decFmt.nrmoff); + const s16 *sv = (const s16*)(ptr_ + nrmoff); + const float fn[3] = { sv[0] / 32768.0f, sv[1] / 32768.0f, sv[2] / 32768.0f }; + Norm3ByMatrix43(normal, fn, skinMatrix); +} + +void VertexDecoder::Step_NormalFloatSkin() const +{ + float *normal = (float *)(decoded_ + decFmt.nrmoff); + const float *fn = (const float *)(ptr_ + nrmoff); + Norm3ByMatrix43(normal, fn, skinMatrix); +} + void VertexDecoder::Step_NormalS8Morph() const { float *normal = (float *)(decoded_ + decFmt.nrmoff); @@ -378,6 +426,29 @@ void VertexDecoder::Step_PosFloat() const memcpy(v, fv, 12); } +void VertexDecoder::Step_PosS8Skin() const +{ + float *pos = (float *)(decoded_ + decFmt.posoff); + const s8 *sv = (const s8*)(ptr_ + posoff); + const float fn[3] = { sv[0] / 128.0f, sv[1] / 128.0f, sv[2] / 128.0f }; + Vec3ByMatrix43(pos, fn, skinMatrix); +} + +void VertexDecoder::Step_PosS16Skin() const +{ + float *pos = (float *)(decoded_ + decFmt.posoff); + const s16 *sv = (const s16*)(ptr_ + posoff); + const float fn[3] = { sv[0] / 32768.0f, sv[1] / 32768.0f, sv[2] / 32768.0f }; + Vec3ByMatrix43(pos, fn, skinMatrix); +} + +void VertexDecoder::Step_PosFloatSkin() const +{ + float *pos = (float *)(decoded_ + decFmt.posoff); + const float *fn = (const float *)(ptr_ + posoff); + Vec3ByMatrix43(pos, fn, skinMatrix); +} + void VertexDecoder::Step_PosS8Through() const { float *v = (float *)(decoded_ + decFmt.posoff); @@ -445,6 +516,13 @@ static const StepFunction wtstep[4] = { &VertexDecoder::Step_WeightsFloat, }; +static const StepFunction wtstep_skin[4] = { + 0, + &VertexDecoder::Step_WeightsU8Skin, + &VertexDecoder::Step_WeightsU16Skin, + &VertexDecoder::Step_WeightsFloatSkin, +}; + static const StepFunction tcstep[4] = { 0, &VertexDecoder::Step_TcU8, @@ -506,6 +584,13 @@ static const StepFunction nrmstep[4] = { &VertexDecoder::Step_NormalFloat, }; +static const StepFunction nrmstep_skin[4] = { + 0, + &VertexDecoder::Step_NormalS8Skin, + &VertexDecoder::Step_NormalS16Skin, + &VertexDecoder::Step_NormalFloatSkin, +}; + static const StepFunction nrmstep_morph[4] = { 0, &VertexDecoder::Step_NormalS8Morph, @@ -520,6 +605,13 @@ static const StepFunction posstep[4] = { &VertexDecoder::Step_PosFloat, }; +static const StepFunction posstep_skin[4] = { + 0, + &VertexDecoder::Step_PosS8Skin, + &VertexDecoder::Step_PosS16Skin, + &VertexDecoder::Step_PosFloatSkin, +}; + static const StepFunction posstep_morph[4] = { 0, &VertexDecoder::Step_PosS8Morph, @@ -560,6 +652,8 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { DEBUG_LOG(G3D,"VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount); } + bool skinInDecode = weighttype != 0 && g_Config.bSoftwareSkinning && morphcount == 1; + if (weighttype) { // && nweights? weightoff = size; //size = align(size, wtalign[weighttype]); unnecessary @@ -567,30 +661,35 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { if (wtalign[weighttype] > biggest) biggest = wtalign[weighttype]; - steps_[numSteps_++] = wtstep[weighttype]; - - int fmtBase = DEC_FLOAT_1; - if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_U8_1; - } else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_U16_1; - } else if (weighttype == GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT) { - fmtBase = DEC_FLOAT_1; - } - - int numWeights = TranslateNumBones(nweights); - - if (numWeights <= 4) { - decFmt.w0off = decOff; - decFmt.w0fmt = fmtBase + numWeights - 1; - decOff += DecFmtSize(decFmt.w0fmt); + if (skinInDecode) { + steps_[numSteps_++] = wtstep_skin[weighttype]; + // No visible output } else { - decFmt.w0off = decOff; - decFmt.w0fmt = fmtBase + 3; - decOff += DecFmtSize(decFmt.w0fmt); - decFmt.w1off = decOff; - decFmt.w1fmt = fmtBase + numWeights - 5; - decOff += DecFmtSize(decFmt.w1fmt); + steps_[numSteps_++] = wtstep[weighttype]; + + int fmtBase = DEC_FLOAT_1; + if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) { + fmtBase = DEC_U8_1; + } else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) { + fmtBase = DEC_U16_1; + } else if (weighttype == GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT) { + fmtBase = DEC_FLOAT_1; + } + + int numWeights = TranslateNumBones(nweights); + + if (numWeights <= 4) { + decFmt.w0off = decOff; + decFmt.w0fmt = fmtBase + numWeights - 1; + decOff += DecFmtSize(decFmt.w0fmt); + } else { + decFmt.w0off = decOff; + decFmt.w0fmt = fmtBase + 3; + decOff += DecFmtSize(decFmt.w0fmt); + decFmt.w1off = decOff; + decFmt.w1fmt = fmtBase + numWeights - 5; + decOff += DecFmtSize(decFmt.w1fmt); + } } } @@ -601,7 +700,8 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { if (tcalign[tc] > biggest) biggest = tcalign[tc]; - if (g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0) { + // NOTE: That we check getUVGenMode here means that we must include it in the decoder ID! + if (g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == 0 || gstate.getUVGenMode() == 3)) { steps_[numSteps_++] = tcstep_prescale[tc]; decFmt.uvfmt = DEC_FLOAT_2; } else { @@ -652,26 +752,29 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { if (nrmalign[nrm] > biggest) biggest = nrmalign[nrm]; - steps_[numSteps_++] = morphcount == 1 ? nrmstep[nrm] : nrmstep_morph[nrm]; - - if (morphcount == 1) { - // The normal formats match the gl formats perfectly, let's use 'em. - switch (nrm) { - case GE_VTYPE_NRM_8BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S8_3; break; - case GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S16_3; break; - case GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_FLOAT_3; break; - } - } else { + if (skinInDecode) { + steps_[numSteps_++] = nrmstep_skin[nrm]; + // After skinning, we always have three floats. decFmt.nrmfmt = DEC_FLOAT_3; - } + } else { + steps_[numSteps_++] = morphcount == 1 ? nrmstep[nrm] : nrmstep_morph[nrm]; - // Actually, temporarily let's not. + if (morphcount == 1) { + // The normal formats match the gl formats perfectly, let's use 'em. + switch (nrm) { + case GE_VTYPE_NRM_8BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S8_3; break; + case GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S16_3; break; + case GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_FLOAT_3; break; + } + } else { + decFmt.nrmfmt = DEC_FLOAT_3; + } + } decFmt.nrmoff = decOff; decOff += DecFmtSize(decFmt.nrmfmt); } - if (pos) // there's always a position - { + if (pos) { // there's always a position size = align(size, posalign[pos]); posoff = size; size += possize[pos]; @@ -682,18 +785,23 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { steps_[numSteps_++] = posstep_through[pos]; decFmt.posfmt = DEC_FLOAT_3; } else { - steps_[numSteps_++] = morphcount == 1 ? posstep[pos] : posstep_morph[pos]; - - if (morphcount == 1) { - // The non-through-mode position formats match the gl formats perfectly, let's use 'em. - switch (pos) { - case GE_VTYPE_POS_8BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S8_3; break; - case GE_VTYPE_POS_16BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S16_3; break; - case GE_VTYPE_POS_FLOAT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_FLOAT_3; break; - } - } else { - // Actually, temporarily let's not. + if (skinInDecode) { + steps_[numSteps_++] = posstep_skin[pos]; decFmt.posfmt = DEC_FLOAT_3; + } else { + steps_[numSteps_++] = morphcount == 1 ? posstep[pos] : posstep_morph[pos]; + + if (morphcount == 1) { + // The non-through-mode position formats match the gl formats perfectly, let's use 'em. + switch (pos) { + case GE_VTYPE_POS_8BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S8_3; break; + case GE_VTYPE_POS_16BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S16_3; break; + case GE_VTYPE_POS_FLOAT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_FLOAT_3; break; + } + } else { + // Actually, temporarily let's not. + decFmt.posfmt = DEC_FLOAT_3; + } } } decFmt.posoff = decOff; @@ -712,6 +820,9 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { // Attempt to JIT as well if (jitCache && g_Config.bVertexDecoderJit) { jitted_ = jitCache->Compile(*this); + if (!jitted_) { + WARN_LOG(G3D, "Vertex decoder JIT failed! fmt = %08x", fmt_);; + } } } @@ -762,8 +873,8 @@ int VertexDecoder::ToString(char *output) const { } VertexDecoderJitCache::VertexDecoderJitCache() { - // 64k should be enough. - AllocCodeSpace(1024 * 64); + // 256k should be enough. + AllocCodeSpace(1024 * 64 * 4); // Add some random code to "help" MSVC's buggy disassembler :( #if defined(_WIN32) @@ -780,953 +891,8 @@ VertexDecoderJitCache::VertexDecoderJitCache() { #endif } -typedef void (VertexDecoderJitCache::*JitStepFunction)(); - -struct JitLookup { - StepFunction func; - JitStepFunction jitFunc; -}; - -static const float by128 = 1.0f / 128.0f; -static const float by32768 = 1.0f / 32768.0f; - -#ifdef ARM - -using namespace ArmGen; - -static const ARMReg tempReg1 = R3; -static const ARMReg tempReg2 = R4; -static const ARMReg tempReg3 = R5; -static const ARMReg scratchReg = R6; -static const ARMReg srcReg = R0; -static const ARMReg dstReg = R1; -static const ARMReg counterReg = R2; -static const ARMReg fpScratchReg = S4; -static const ARMReg fpScratchReg2 = S5; -static const ARMReg fpUscaleReg = S0; -static const ARMReg fpVscaleReg = S1; -static const ARMReg fpUoffsetReg = S2; -static const ARMReg fpVoffsetReg = S3; - -static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, - - {&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8}, - {&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16}, - {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, - {&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double}, - - {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, - {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, - {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, - - {&VertexDecoder::Step_TcU16Through, &VertexDecoderJitCache::Jit_TcU16Through}, - {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, - {&VertexDecoder::Step_TcU16ThroughDouble, &VertexDecoderJitCache::Jit_TcU16ThroughDouble}, - - {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, - {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, - {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, - - {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, - {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, - {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, - {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, - - {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, - {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, - {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloat}, - - {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, - {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, - {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, -}; - -JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec) { - dec_ = &dec; - const u8 *start = this->GetCodePtr(); - - bool prescaleStep = false; - // Look for prescaled texcoord steps - for (int i = 0; i < dec.numSteps_; i++) { - if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { - prescaleStep = true; - } - } - - SetCC(CC_AL); - - PUSH(6, R4, R5, R6, R7, R8, _LR); - - // Keep the scale/offset in a few fp registers if we need it. - if (prescaleStep) { - MOVI2R(R3, (u32)(&gstate_c.uv), scratchReg); - VLDR(fpUscaleReg, R3, 0); - VLDR(fpVscaleReg, R3, 4); - VLDR(fpUoffsetReg, R3, 8); - VLDR(fpVoffsetReg, R3, 12); - if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { - MOVI2F(fpScratchReg, by128, scratchReg); - VMUL(fpUscaleReg, fpUscaleReg, fpScratchReg); - VMUL(fpVscaleReg, fpVscaleReg, fpScratchReg); - } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { - MOVI2F(fpScratchReg, by32768, scratchReg); - VMUL(fpUscaleReg, fpUscaleReg, fpScratchReg); - VMUL(fpVscaleReg, fpVscaleReg, fpScratchReg); - } - } - - JumpTarget loopStart = GetCodePtr(); - for (int i = 0; i < dec.numSteps_; i++) { - if (!CompileStep(dec, i)) { - // Reset the code ptr and return zero to indicate that we failed. - SetCodePtr(const_cast(start)); - char temp[1024] = {0}; - dec.ToString(temp); - INFO_LOG(HLE, "Could not compile vertex decoder: %s", temp); - return 0; - } - } - - ADDI2R(srcReg, srcReg, dec.VertexSize(), scratchReg); - ADDI2R(dstReg, dstReg, dec.decFmt.stride, scratchReg); - SUBS(counterReg, counterReg, 1); - B_CC(CC_NEQ, loopStart); - - POP(6, R4, R5, R6, R7, R8, _PC); - - FlushIcache(); - - // DisassembleArm(start, GetCodePtr() - start); - // char temp[1024] = {0}; - // dec.ToString(temp); - // INFO_LOG(HLE, "%s", temp); - - return (JittedVertexDecoder)start; -} - -void VertexDecoderJitCache::Jit_WeightsU8() { - // Basic implementation - a byte at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRB(tempReg1, srcReg, dec_->weightoff + j); - STRB(tempReg1, dstReg, dec_->decFmt.w0off + j); - } - if (j & 3) { - // Create a zero register. Might want to make a fixed one. - EOR(scratchReg, scratchReg, scratchReg); - } - while (j & 3) { - STRB(scratchReg, dstReg, dec_->decFmt.w0off + j); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsU16() { - // Basic implementation - a short at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - LDRH(tempReg1, srcReg, dec_->weightoff + j * 2); - STRH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2); - } - if (j & 3) { - // Create a zero register. Might want to make a fixed one. - EOR(scratchReg, scratchReg, scratchReg); - } - while (j & 3) { - STRH(scratchReg, dstReg, dec_->decFmt.w0off + j * 2); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { - int j; - for (j = 0; j < dec_->nweights; j++) { - LDR(tempReg1, srcReg, dec_->weightoff + j * 4); - STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); - } - if (j & 3) { - // Create a zero register. Might want to make a fixed one. - EOR(scratchReg, scratchReg, scratchReg); - } - while (j & 3) { // Zero additional weights rounding up to 4. - STR(scratchReg, dstReg, dec_->decFmt.w0off + j * 4); - j++; - } -} - -// Fill last two bytes with zeroes to align to 4 bytes. LDRH does it for us, handy. -void VertexDecoderJitCache::Jit_TcU8() { - LDRB(tempReg1, srcReg, dec_->tcoff); - LDRB(tempReg2, srcReg, dec_->tcoff + 1); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); -} - -void VertexDecoderJitCache::Jit_TcU16() { - LDRH(tempReg1, srcReg, dec_->tcoff); - LDRH(tempReg2, srcReg, dec_->tcoff + 2); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); -} - -void VertexDecoderJitCache::Jit_TcFloat() { - LDR(tempReg1, srcReg, dec_->tcoff); - LDR(tempReg2, srcReg, dec_->tcoff + 4); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); - STR(tempReg2, dstReg, dec_->decFmt.uvoff + 4); -} - -void VertexDecoderJitCache::Jit_TcU16Through() { - LDRH(tempReg1, srcReg, dec_->tcoff); - LDRH(tempReg2, srcReg, dec_->tcoff + 2); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); -} - -void VertexDecoderJitCache::Jit_TcFloatThrough() { - LDR(tempReg1, srcReg, dec_->tcoff); - LDR(tempReg2, srcReg, dec_->tcoff + 4); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); - STR(tempReg2, dstReg, dec_->decFmt.uvoff + 4); -} - -void VertexDecoderJitCache::Jit_TcU16Double() { - LDRH(tempReg1, srcReg, dec_->tcoff); - LDRH(tempReg2, srcReg, dec_->tcoff + 2); - LSL(tempReg1, tempReg1, 1); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 17)); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); -} - -void VertexDecoderJitCache::Jit_TcU16ThroughDouble() { - LDRH(tempReg1, srcReg, dec_->tcoff); - LDRH(tempReg2, srcReg, dec_->tcoff + 2); - LSL(tempReg1, tempReg1, 1); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 17)); - STR(tempReg1, dstReg, dec_->decFmt.uvoff); -} - -void VertexDecoderJitCache::Jit_TcU8Prescale() { - // TODO: SIMD - LDRB(tempReg1, srcReg, dec_->tcoff); - LDRB(tempReg2, srcReg, dec_->tcoff + 1); - VMOV(fpScratchReg, tempReg1); - VMOV(fpScratchReg2, tempReg2); - VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); - VCVT(fpScratchReg2, fpScratchReg2, TO_FLOAT); - // Could replace VMUL + VADD with VMLA but would require 2 more regs as we don't want to destroy fp*offsetReg. Later. - VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); - VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); - VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); - VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); - VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); - VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); -} - -void VertexDecoderJitCache::Jit_TcU16Prescale() { - // TODO: SIMD - LDRH(tempReg1, srcReg, dec_->tcoff); - LDRH(tempReg2, srcReg, dec_->tcoff + 2); - VMOV(fpScratchReg, tempReg1); - VMOV(fpScratchReg2, tempReg2); - VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); - VCVT(fpScratchReg2, fpScratchReg2, TO_FLOAT); - VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); - VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); - VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); - VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); - VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); - VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); -} - -void VertexDecoderJitCache::Jit_TcFloatPrescale() { - // TODO: SIMD - VLDR(fpScratchReg, srcReg, dec_->tcoff); - VLDR(fpScratchReg2, srcReg, dec_->tcoff + 4); - VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); - VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); - VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); - VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); - VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); - VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); -} - -void VertexDecoderJitCache::Jit_Color8888() { - LDR(tempReg1, srcReg, dec_->coloff); - STR(tempReg1, dstReg, dec_->decFmt.c0off); -} - -void VertexDecoderJitCache::Jit_Color4444() { - LDRH(tempReg1, srcReg, dec_->coloff); - - // Spread out the components. - ANDI2R(tempReg2, tempReg1, 0x000F, scratchReg); - ANDI2R(tempReg3, tempReg1, 0x00F0, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 4)); - ANDI2R(tempReg3, tempReg1, 0x0F00, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 8)); - ANDI2R(tempReg3, tempReg1, 0xF000, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 12)); - - // And saturate. - ORR(tempReg1, tempReg2, Operand2(tempReg2, ST_LSL, 4)); - - STR(tempReg1, dstReg, dec_->decFmt.c0off); -} - -void VertexDecoderJitCache::Jit_Color565() { - LDRH(tempReg1, srcReg, dec_->coloff); - - // Spread out R and B first. This puts them in 0x001F001F. - ANDI2R(tempReg2, tempReg1, 0x001F, scratchReg); - ANDI2R(tempReg3, tempReg1, 0xF800, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 5)); - - // Expand 5 -> 8. - LSL(tempReg3, tempReg2, 3); - ORR(tempReg2, tempReg3, Operand2(tempReg2, ST_LSR, 2)); - ANDI2R(tempReg2, tempReg2, 0xFFFF00FF, scratchReg); - - // Now finally G. We start by shoving it into a wall. - LSR(tempReg1, tempReg1, 5); - ANDI2R(tempReg1, tempReg1, 0x003F, scratchReg); - LSL(tempReg3, tempReg1, 2); - // Don't worry, shifts into a wall. - ORR(tempReg3, tempReg3, Operand2(tempReg1, ST_LSR, 4)); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 8)); - - // Add in full alpha. - ORI2R(tempReg1, tempReg2, 0xFF000000, scratchReg); - - STR(tempReg1, dstReg, dec_->decFmt.c0off); -} - -void VertexDecoderJitCache::Jit_Color5551() { - LDRH(tempReg1, srcReg, dec_->coloff); - - ANDI2R(tempReg2, tempReg1, 0x001F, scratchReg); - ANDI2R(tempReg3, tempReg1, 0x07E0, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 3)); - ANDI2R(tempReg3, tempReg1, 0xF800, scratchReg); - ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 6)); - - // Expand 5 -> 8. - LSR(tempReg3, tempReg2, 2); - // Clean up the bits that were shifted right. - BIC(tempReg3, tempReg1, AssumeMakeOperand2(0x000000F8)); - BIC(tempReg3, tempReg3, AssumeMakeOperand2(0x0000F800)); - ORR(tempReg2, tempReg3, Operand2(tempReg2, ST_LSL, 3)); - - // Now we just need alpha. - TSTI2R(tempReg1, 0x8000, scratchReg); - SetCC(CC_NEQ); - ORI2R(tempReg2, tempReg2, 0xFF000000, scratchReg); - SetCC(CC_AL); - - STR(tempReg2, dstReg, dec_->decFmt.c0off); -} - -void VertexDecoderJitCache::Jit_NormalS8() { - LDRB(tempReg1, srcReg, dec_->nrmoff); - LDRB(tempReg2, srcReg, dec_->nrmoff + 1); - LDRB(tempReg3, srcReg, dec_->nrmoff + 2); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); - ORR(tempReg1, tempReg1, Operand2(tempReg3, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.nrmoff); - - // Copy 3 bytes and then a zero. Might as well copy four. - // LDR(tempReg1, srcReg, dec_->nrmoff); - // ANDI2R(tempReg1, tempReg1, 0x00FFFFFF, scratchReg); - // STR(tempReg1, dstReg, dec_->decFmt.nrmoff); -} - -// Copy 6 bytes and then 2 zeroes. -void VertexDecoderJitCache::Jit_NormalS16() { - LDRH(tempReg1, srcReg, dec_->nrmoff); - LDRH(tempReg2, srcReg, dec_->nrmoff + 2); - LDRH(tempReg3, srcReg, dec_->nrmoff + 4); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.nrmoff); - STR(tempReg3, dstReg, dec_->decFmt.nrmoff + 4); -} - -void VertexDecoderJitCache::Jit_NormalFloat() { - // Might not be aligned to 4, so we can't use LDMIA. - // Actually - not true: This will always be aligned. TODO - LDR(tempReg1, srcReg, dec_->nrmoff); - LDR(tempReg2, srcReg, dec_->nrmoff + 4); - LDR(tempReg3, srcReg, dec_->nrmoff + 8); - // But this is always aligned to 4 so we're safe. - ADD(scratchReg, dstReg, dec_->decFmt.nrmoff); - STMIA(scratchReg, false, 3, tempReg1, tempReg2, tempReg3); -} - -// Through expands into floats, always. Might want to look at changing this. -void VertexDecoderJitCache::Jit_PosS8Through() { - // TODO: SIMD - LDRSB(tempReg1, srcReg, dec_->posoff); - LDRSB(tempReg2, srcReg, dec_->posoff + 1); - LDRSB(tempReg3, srcReg, dec_->posoff + 2); - static const ARMReg tr[3] = { tempReg1, tempReg2, tempReg3 }; - for (int i = 0; i < 3; i++) { - VMOV(fpScratchReg, tr[i]); - VCVT(fpScratchReg, fpScratchReg, TO_FLOAT | IS_SIGNED); - VSTR(fpScratchReg, dstReg, dec_->decFmt.posoff + i * 4); - } -} - -// Through expands into floats, always. Might want to look at changing this. -void VertexDecoderJitCache::Jit_PosS16Through() { - // TODO: SIMD - LDRSH(tempReg1, srcReg, dec_->posoff); - LDRSH(tempReg2, srcReg, dec_->posoff + 2); - LDRSH(tempReg3, srcReg, dec_->posoff + 4); - static const ARMReg tr[3] = { tempReg1, tempReg2, tempReg3 }; - for (int i = 0; i < 3; i++) { - VMOV(fpScratchReg, tr[i]); - VCVT(fpScratchReg, fpScratchReg, TO_FLOAT | IS_SIGNED); - VSTR(fpScratchReg, dstReg, dec_->decFmt.posoff + i * 4); - } -} - -// Copy 3 bytes and then a zero. Might as well copy four. -void VertexDecoderJitCache::Jit_PosS8() { - LDRB(tempReg1, srcReg, dec_->posoff); - LDRB(tempReg2, srcReg, dec_->posoff + 1); - LDRB(tempReg3, srcReg, dec_->posoff + 2); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); - ORR(tempReg1, tempReg1, Operand2(tempReg3, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.posoff); -} - -// Copy 6 bytes and then 2 zeroes. -void VertexDecoderJitCache::Jit_PosS16() { - LDRH(tempReg1, srcReg, dec_->posoff); - LDRH(tempReg2, srcReg, dec_->posoff + 2); - LDRH(tempReg3, srcReg, dec_->posoff + 4); - ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); - STR(tempReg1, dstReg, dec_->decFmt.posoff); - STR(tempReg3, dstReg, dec_->decFmt.posoff + 4); -} - -// Just copy 12 bytes. -void VertexDecoderJitCache::Jit_PosFloat() { - // Might not be aligned to 4, so we can't use LDMIA. - LDR(tempReg1, srcReg, dec_->posoff); - LDR(tempReg2, srcReg, dec_->posoff + 4); - LDR(tempReg3, srcReg, dec_->posoff + 8); - // But this is always aligned to 4 so we're safe. - ADD(scratchReg, dstReg, dec_->decFmt.posoff); - STMIA(scratchReg, false, 3, tempReg1, tempReg2, tempReg3); -} - -#elif defined(_M_X64) || defined(_M_IX86) - -using namespace Gen; - -#ifdef _M_X64 -#ifdef _WIN32 -static const X64Reg tempReg1 = RAX; -static const X64Reg tempReg2 = R9; -static const X64Reg tempReg3 = R10; -static const X64Reg srcReg = RCX; -static const X64Reg dstReg = RDX; -static const X64Reg counterReg = R8; -#else -static const X64Reg tempReg1 = RAX; -static const X64Reg tempReg2 = R9; -static const X64Reg tempReg3 = R10; -static const X64Reg srcReg = RDI; -static const X64Reg dstReg = RSI; -static const X64Reg counterReg = RDX; -#endif -#else -static const X64Reg tempReg1 = EAX; -static const X64Reg tempReg2 = EBX; -static const X64Reg tempReg3 = EDX; -static const X64Reg srcReg = ESI; -static const X64Reg dstReg = EDI; -static const X64Reg counterReg = ECX; -#endif - -// XMM0-XMM5 are volatile on Windows X64 -// XMM0-XMM7 are arguments (and thus volatile) on System V ABI (other x64 platforms) -static const X64Reg fpUscaleReg = XMM0; -static const X64Reg fpVscaleReg = XMM1; -static const X64Reg fpUoffsetReg = XMM2; -static const X64Reg fpVoffsetReg = XMM3; -static const X64Reg fpScratchReg = XMM4; -static const X64Reg fpScratchReg2 = XMM5; - -// To debug, just comment them out one at a time until it works. We fall back -// on the interpreter if the compiler fails. - -static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, - - {&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8}, - {&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16}, - {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, - {&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double}, - - {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, - {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, - {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, - - {&VertexDecoder::Step_TcU16Through, &VertexDecoderJitCache::Jit_TcU16Through}, - {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, - {&VertexDecoder::Step_TcU16ThroughDouble, &VertexDecoderJitCache::Jit_TcU16ThroughDouble}, - - {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, - {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, - {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, - - {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, - {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, - {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, - {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, - - {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, - {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, - {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloat}, - - {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, - {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, - {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, -}; - -// TODO: This should probably be global... -#ifdef _M_X64 -#define PTRBITS 64 -#else -#define PTRBITS 32 -#endif - -JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec) { - dec_ = &dec; - const u8 *start = this->GetCodePtr(); - -#ifdef _M_IX86 - // Store register values - PUSH(ESI); - PUSH(EDI); - PUSH(EBX); - PUSH(EBP); - - // Read parameters - int offset = 4; - MOV(32, R(srcReg), MDisp(ESP, 16 + offset + 0)); - MOV(32, R(dstReg), MDisp(ESP, 16 + offset + 4)); - MOV(32, R(counterReg), MDisp(ESP, 16 + offset + 8)); -#endif - - // Save XMM4/XMM5 which apparently can be problematic? - // Actually, if they are, it must be a compiler bug because they SHOULD be ok. - // So I won't bother. - // SUB(PTRBITS, R(ESP), Imm8(32)); - // MOVUPS(MDisp(ESP, 0), XMM4); - // MOVUPS(MDisp(ESP, 16), XMM5); - - bool prescaleStep = false; - // Look for prescaled texcoord steps - for (int i = 0; i < dec.numSteps_; i++) { - if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { - prescaleStep = true; - } - } - - // Keep the scale/offset in a few fp registers if we need it. - if (prescaleStep) { -#ifdef _M_X64 - MOV(64, R(tempReg1), Imm64((u64)(&gstate_c.uv))); -#else - MOV(32, R(tempReg1), Imm32((u32)(&gstate_c.uv))); -#endif - MOVSS(fpUscaleReg, MDisp(tempReg1, 0)); - MOVSS(fpVscaleReg, MDisp(tempReg1, 4)); - MOVSS(fpUoffsetReg, MDisp(tempReg1, 8)); - MOVSS(fpVoffsetReg, MDisp(tempReg1, 12)); - if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { - MULSS(fpUscaleReg, M((void *)&by128)); - MULSS(fpVscaleReg, M((void *)&by128)); - } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { - MULSS(fpUscaleReg, M((void *)&by32768)); - MULSS(fpVscaleReg, M((void *)&by32768)); - } - } - - // Let's not bother with a proper stack frame. We just grab the arguments and go. - JumpTarget loopStart = GetCodePtr(); - for (int i = 0; i < dec.numSteps_; i++) { - if (!CompileStep(dec, i)) { - // Reset the code ptr and return zero to indicate that we failed. - SetCodePtr(const_cast(start)); - return 0; - } - } - - ADD(PTRBITS, R(srcReg), Imm32(dec.VertexSize())); - ADD(PTRBITS, R(dstReg), Imm32(dec.decFmt.stride)); - SUB(32, R(counterReg), Imm8(1)); - J_CC(CC_NZ, loopStart, true); - - // MOVUPS(XMM4, MDisp(ESP, 0)); - // MOVUPS(XMM5, MDisp(ESP, 16)); - // ADD(PTRBITS, R(ESP), Imm8(32)); - -#ifdef _M_IX86 - // Restore register values - POP(EBP); - POP(EBX); - POP(EDI); - POP(ESI); -#endif - - RET(); - - return (JittedVertexDecoder)start; -} - -void VertexDecoderJitCache::Jit_WeightsU8() { - // Basic implementation - a byte at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - MOV(8, R(tempReg1), MDisp(srcReg, dec_->weightoff + j)); - MOV(8, MDisp(dstReg, dec_->decFmt.w0off + j), R(tempReg1)); - } - while (j & 3) { - MOV(8, MDisp(dstReg, dec_->decFmt.w0off + j), Imm8(0)); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsU16() { - // Basic implementation - a short at a time. TODO: Optimize - int j; - for (j = 0; j < dec_->nweights; j++) { - MOV(16, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 2)); - MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), R(tempReg1)); - } - while (j & 3) { - MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), Imm16(0)); - j++; - } -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { - int j; - for (j = 0; j < dec_->nweights; j++) { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), R(tempReg1)); - } - while (j & 3) { // Zero additional weights rounding up to 4. - MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), Imm32(0)); - j++; - } -} - -// Fill last two bytes with zeroes to align to 4 bytes. MOVZX does it for us, handy. -void VertexDecoderJitCache::Jit_TcU8() { - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_TcU16() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_TcU16Double() { - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->tcoff + 2)); - SHL(16, R(tempReg1), Imm8(1)); // 16 to get a wall to shift into - SHL(32, R(tempReg2), Imm8(17)); - OR(32, R(tempReg1), R(tempReg2)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_TcFloat() { -#ifdef _M_X64 - MOV(64, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(64, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -#else - MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->tcoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff + 4), R(tempReg2)); -#endif -} - -void VertexDecoderJitCache::Jit_TcU8Prescale() { - // TODO: SIMD - MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->tcoff)); - MOVZX(32, 8, tempReg2, MDisp(srcReg, dec_->tcoff + 1)); - CVTSI2SS(fpScratchReg, R(tempReg1)); - CVTSI2SS(fpScratchReg2, R(tempReg2)); - MULSS(fpScratchReg, R(fpUscaleReg)); - MULSS(fpScratchReg2, R(fpVscaleReg)); - ADDSS(fpScratchReg, R(fpUoffsetReg)); - ADDSS(fpScratchReg2, R(fpVoffsetReg)); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff + 4), fpScratchReg2); -} - -void VertexDecoderJitCache::Jit_TcU16Prescale() { - // TODO: SIMD - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->tcoff + 2)); - CVTSI2SS(fpScratchReg, R(tempReg1)); - CVTSI2SS(fpScratchReg2, R(tempReg2)); - MULSS(fpScratchReg, R(fpUscaleReg)); - MULSS(fpScratchReg2, R(fpVscaleReg)); - ADDSS(fpScratchReg, R(fpUoffsetReg)); - ADDSS(fpScratchReg2, R(fpVoffsetReg)); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff + 4), fpScratchReg2); -} - -void VertexDecoderJitCache::Jit_TcFloatPrescale() { - // TODO: SIMD - MOVSS(fpScratchReg, MDisp(srcReg, dec_->tcoff)); - MOVSS(fpScratchReg2, MDisp(srcReg, dec_->tcoff + 4)); - MULSS(fpScratchReg, R(fpUscaleReg)); - MULSS(fpScratchReg2, R(fpVscaleReg)); - ADDSS(fpScratchReg, R(fpUoffsetReg)); - ADDSS(fpScratchReg2, R(fpVoffsetReg)); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); - MOVSS(MDisp(dstReg, dec_->decFmt.uvoff + 4), fpScratchReg2); -} - -void VertexDecoderJitCache::Jit_TcU16Through() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_TcU16ThroughDouble() { - MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->tcoff + 2)); - SHL(16, R(tempReg1), Imm8(1)); // 16 to get a wall to shift into - SHL(32, R(tempReg2), Imm8(17)); - OR(32, R(tempReg1), R(tempReg2)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_TcFloatThrough() { -#ifdef _M_X64 - MOV(64, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(64, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); -#else - MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->tcoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.uvoff + 4), R(tempReg2)); -#endif -} - -void VertexDecoderJitCache::Jit_Color8888() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->coloff)); - MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg1)); -} - -void VertexDecoderJitCache::Jit_Color4444() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->coloff)); - - // 0000ABGR, copy R and double forwards. - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x0000000F)); - MOV(32, R(tempReg2), R(tempReg3)); - SHL(32, R(tempReg3), Imm8(4)); - OR(32, R(tempReg2), R(tempReg3)); - - // tempReg1 -> 00ABGR00, then double G backwards. - SHL(32, R(tempReg1), Imm8(8)); - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x0000F000)); - OR(32, R(tempReg2), R(tempReg3)); - SHR(32, R(tempReg3), Imm8(4)); - OR(32, R(tempReg2), R(tempReg3)); - - // Now do B forwards again (still 00ABGR00.) - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x000F0000)); - OR(32, R(tempReg2), R(tempReg3)); - SHL(32, R(tempReg3), Imm8(4)); - OR(32, R(tempReg2), R(tempReg3)); - - // tempReg1 -> ABGR0000, then double A backwards. - SHL(32, R(tempReg1), Imm8(8)); - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0xF0000000)); - OR(32, R(tempReg2), R(tempReg3)); - SHR(32, R(tempReg3), Imm8(4)); - OR(32, R(tempReg2), R(tempReg3)); - - MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); -} - -void VertexDecoderJitCache::Jit_Color565() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->coloff)); - - MOV(32, R(tempReg2), R(tempReg1)); - AND(32, R(tempReg2), Imm32(0x0000001F)); - - // B (we do R and B at the same time, they're both 5.) - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x0000F800)); - SHL(32, R(tempReg3), Imm8(5)); - OR(32, R(tempReg2), R(tempReg3)); - - // Expand 5 -> 8. At this point we have 00BB00RR. - MOV(32, R(tempReg3), R(tempReg2)); - SHL(32, R(tempReg2), Imm8(3)); - SHR(32, R(tempReg3), Imm8(2)); - OR(32, R(tempReg2), R(tempReg3)); - AND(32, R(tempReg2), Imm32(0x00FF00FF)); - - // Now's as good a time to put in A as any. - OR(32, R(tempReg2), Imm32(0xFF000000)); - - // Last, we need to align, extract, and expand G. - // 3 to align to G, and then 2 to expand to 8. - SHL(32, R(tempReg1), Imm8(3 + 2)); - AND(32, R(tempReg1), Imm32(0x0000FC00)); - MOV(32, R(tempReg3), R(tempReg1)); - // 2 to account for tempReg1 being preshifted, 4 for expansion. - SHR(32, R(tempReg3), Imm8(2 + 4)); - OR(32, R(tempReg1), R(tempReg3)); - AND(32, R(tempReg1), Imm32(0x0000FF00)); - OR(32, R(tempReg2), R(tempReg1)); - - MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); -} - -void VertexDecoderJitCache::Jit_Color5551() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->coloff)); - - MOV(32, R(tempReg2), R(tempReg1)); - AND(32, R(tempReg2), Imm32(0x0000001F)); - - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x000003E0)); - SHL(32, R(tempReg3), Imm8(3)); - OR(32, R(tempReg2), R(tempReg3)); - - MOV(32, R(tempReg3), R(tempReg1)); - AND(32, R(tempReg3), Imm32(0x00007C00)); - SHL(32, R(tempReg3), Imm8(6)); - OR(32, R(tempReg2), R(tempReg3)); - - // Expand 5 -> 8. After this is just A. - MOV(32, R(tempReg3), R(tempReg2)); - SHL(32, R(tempReg2), Imm8(3)); - SHR(32, R(tempReg3), Imm8(2)); - // Chop off the bits that were shifted out. - AND(32, R(tempReg3), Imm32(0x00070707)); - OR(32, R(tempReg2), R(tempReg3)); - - // For A, we shift it to a single bit, and then subtract and XOR. - // That's probably the simplest way to expand it... - SHR(32, R(tempReg1), Imm8(15)); - // If it was 0, it's now -1, otherwise it's 0. Easy. - SUB(32, R(tempReg1), Imm8(1)); - XOR(32, R(tempReg1), Imm32(0xFF000000)); - AND(32, R(tempReg1), Imm32(0xFF000000)); - OR(32, R(tempReg2), R(tempReg1)); - - MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); -} - -// Copy 3 bytes and then a zero. Might as well copy four. -void VertexDecoderJitCache::Jit_NormalS8() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); - AND(32, R(tempReg1), Imm32(0x00FFFFFF)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); -} - -// Copy 6 bytes and then 2 zeroes. -void VertexDecoderJitCache::Jit_NormalS16() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->nrmoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2)); -} - -void VertexDecoderJitCache::Jit_NormalFloat() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->nrmoff + 4)); - MOV(32, R(tempReg3), MDisp(srcReg, dec_->nrmoff + 8)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2)); - MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 8), R(tempReg3)); -} - -// Through expands into floats, always. Might want to look at changing this. -void VertexDecoderJitCache::Jit_PosS8Through() { - // TODO: SIMD - for (int i = 0; i < 3; i++) { - MOVSX(32, 8, tempReg1, MDisp(srcReg, dec_->posoff + i)); - CVTSI2SS(fpScratchReg, R(tempReg1)); - MOVSS(MDisp(dstReg, dec_->decFmt.posoff + i * 4), fpScratchReg); - } -} - -// Through expands into floats, always. Might want to look at changing this. -void VertexDecoderJitCache::Jit_PosS16Through() { - // TODO: SIMD - for (int i = 0; i < 3; i++) { - MOVSX(32, 16, tempReg1, MDisp(srcReg, dec_->posoff + i * 2)); - CVTSI2SS(fpScratchReg, R(tempReg1)); - MOVSS(MDisp(dstReg, dec_->decFmt.posoff + i * 4), fpScratchReg); - } -} - -// Copy 3 bytes and then a zero. Might as well copy four. -void VertexDecoderJitCache::Jit_PosS8() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); - AND(32, R(tempReg1), Imm32(0x00FFFFFF)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); -} - -// Copy 6 bytes and then 2 zeroes. -void VertexDecoderJitCache::Jit_PosS16() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); - MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->posoff + 4)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2)); -} - -// Just copy 12 bytes. -void VertexDecoderJitCache::Jit_PosFloat() { - MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); - MOV(32, R(tempReg2), MDisp(srcReg, dec_->posoff + 4)); - MOV(32, R(tempReg3), MDisp(srcReg, dec_->posoff + 8)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2)); - MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3)); -} - -#elif defined(PPC) +#if defined(PPC) #error This should not be built for PowerPC, at least not yet. #endif - -bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { - // See if we find a matching JIT function - for (size_t i = 0; i < ARRAY_SIZE(jitLookup); i++) { - if (dec.steps_[step] == jitLookup[i].func) { - ((*this).*jitLookup[i].jitFunc)(); - return true; - } - } - return false; -} diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index dfa248140c..ab974aef00 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -34,7 +34,12 @@ class VertexDecoder; class VertexDecoderJitCache; typedef void (VertexDecoder::*StepFunction)() const; +typedef void (VertexDecoderJitCache::*JitStepFunction)(); +struct JitLookup { + StepFunction func; + JitStepFunction jitFunc; +}; typedef void (*JittedVertexDecoder)(const u8 *src, u8 *dst, int count); @@ -64,6 +69,10 @@ public: void Step_WeightsU16() const; void Step_WeightsFloat() const; + void Step_WeightsU8Skin() const; + void Step_WeightsU16Skin() const; + void Step_WeightsFloatSkin() const; + void Step_TcU8() const; void Step_TcU16() const; void Step_TcFloat() const; @@ -91,6 +100,10 @@ public: void Step_NormalS16() const; void Step_NormalFloat() const; + void Step_NormalS8Skin() const; + void Step_NormalS16Skin() const; + void Step_NormalFloatSkin() const; + void Step_NormalS8Morph() const; void Step_NormalS16Morph() const; void Step_NormalFloatMorph() const; @@ -99,6 +112,10 @@ public: void Step_PosS16() const; void Step_PosFloat() const; + void Step_PosS8Skin() const; + void Step_PosS16Skin() const; + void Step_PosFloatSkin() const; + void Step_PosS8Morph() const; void Step_PosS16Morph() const; void Step_PosFloatMorph() const; @@ -187,6 +204,10 @@ public: void Jit_WeightsU16(); void Jit_WeightsFloat(); + void Jit_WeightsU8Skin(); + void Jit_WeightsU16Skin(); + void Jit_WeightsFloatSkin(); + void Jit_TcU8(); void Jit_TcU16(); void Jit_TcFloat(); @@ -210,13 +231,23 @@ public: void Jit_NormalS16(); void Jit_NormalFloat(); + void Jit_NormalS8Skin(); + void Jit_NormalS16Skin(); + void Jit_NormalFloatSkin(); + void Jit_PosS8(); - void Jit_PosS8Through(); void Jit_PosS16(); - void Jit_PosS16Through(); void Jit_PosFloat(); + void Jit_PosS8Through(); + void Jit_PosS16Through(); + + void Jit_PosS8Skin(); + void Jit_PosS16Skin(); + void Jit_PosFloatSkin(); private: bool CompileStep(const VertexDecoder &dec, int i); + void Jit_ApplyWeights(); + void Jit_WriteMatrixMul(int outOff, bool pos); const VertexDecoder *dec_; }; diff --git a/GPU/GLES/VertexDecoderArm.cpp b/GPU/GLES/VertexDecoderArm.cpp new file mode 100644 index 0000000000..7aeb4b1923 --- /dev/null +++ b/GPU/GLES/VertexDecoderArm.cpp @@ -0,0 +1,931 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "base/logging.h" +#include "Common/CPUDetect.h" +#include "Core/Config.h" +#include "GPU/GLES/VertexDecoder.h" + +extern void DisassembleArm(const u8 *data, int size); + +bool NEONSkinning = false; + +// Used only in non-NEON mode. +static float MEMORY_ALIGNED16(skinMatrix[12]); + +// Will be used only in NEON mode. +static float MEMORY_ALIGNED16(bones[16 * 8]); // First two are kept in registers + +// NEON register allocation: +// Q0: Texture scaling parameters +// Q1: Temp storage +// Q2: Vector-by-matrix accumulator +// Q3: Unused +// +// We'll use Q4-Q7 as the "matrix accumulator". +// First two matrices will be preloaded into Q8-Q11 and Q12-Q15 to reduce +// memory bandwidth requirements. +// The rest will be dumped to bones as on x86. + + +static const float by128 = 1.0f / 128.0f; +static const float by256 = 1.0f / 256.0f; +static const float by32768 = 1.0f / 32768.0f; + +using namespace ArmGen; + +static const ARMReg tempReg1 = R3; +static const ARMReg tempReg2 = R4; +static const ARMReg tempReg3 = R5; +static const ARMReg scratchReg = R6; +static const ARMReg scratchReg2 = R7; +static const ARMReg scratchReg3 = R12; +static const ARMReg srcReg = R0; +static const ARMReg dstReg = R1; +static const ARMReg counterReg = R2; +static const ARMReg fpScratchReg = S4; +static const ARMReg fpScratchReg2 = S5; +static const ARMReg fpScratchReg3 = S6; +static const ARMReg fpScratchReg4 = S7; +static const ARMReg fpUscaleReg = S0; +static const ARMReg fpVscaleReg = S1; +static const ARMReg fpUoffsetReg = S2; +static const ARMReg fpVoffsetReg = S3; + +// Simpler aliases for NEON. Overlaps with corresponding VFP regs. +static const ARMReg neonUVScaleReg = D0; +static const ARMReg neonUVOffsetReg = D1; +static const ARMReg neonScratchReg = D2; +static const ARMReg neonScratchRegQ = Q1; // Overlaps with all the scratch regs + +// Everything above S6 is fair game for skinning + +// S8-S15 are used during matrix generation + +// These only live through the matrix multiplication +static const ARMReg src[3] = {S8, S9, S10}; // skin source +static const ARMReg acc[3] = {S11, S12, S13}; // skin accumulator + +static const ARMReg srcNEON = Q2; +static const ARMReg accNEON = Q3; + +static const JitLookup jitLookup[] = { + {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, + {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, + {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, + + {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, + {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, + {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, + + {&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8}, + {&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16}, + {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, + {&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double}, + + {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, + {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, + {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, + + {&VertexDecoder::Step_TcU16Through, &VertexDecoderJitCache::Jit_TcU16Through}, + {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, + {&VertexDecoder::Step_TcU16ThroughDouble, &VertexDecoderJitCache::Jit_TcU16ThroughDouble}, + + {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, + {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, + {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, + + {&VertexDecoder::Step_NormalS8Skin, &VertexDecoderJitCache::Jit_NormalS8Skin}, + {&VertexDecoder::Step_NormalS16Skin, &VertexDecoderJitCache::Jit_NormalS16Skin}, + {&VertexDecoder::Step_NormalFloatSkin, &VertexDecoderJitCache::Jit_NormalFloatSkin}, + + {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, + {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, + {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, + {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, + + {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, + {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, + {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloat}, + + {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, + {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, + {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, + + {&VertexDecoder::Step_PosS8Skin, &VertexDecoderJitCache::Jit_PosS8Skin}, + {&VertexDecoder::Step_PosS16Skin, &VertexDecoderJitCache::Jit_PosS16Skin}, + {&VertexDecoder::Step_PosFloatSkin, &VertexDecoderJitCache::Jit_PosFloatSkin}, +}; + +JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec) { + dec_ = &dec; + const u8 *start = AlignCode16(); + + bool prescaleStep = false; + bool skinning = false; + + NEONSkinning = cpu_info.bNEON; + + // Look for prescaled texcoord steps + for (int i = 0; i < dec.numSteps_; i++) { + if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { + prescaleStep = true; + } + if (dec.steps_[i] == &VertexDecoder::Step_WeightsU8Skin || + dec.steps_[i] == &VertexDecoder::Step_WeightsU16Skin || + dec.steps_[i] == &VertexDecoder::Step_WeightsFloatSkin) { + skinning = true; + } + } + + SetCC(CC_AL); + + PUSH(6, R4, R5, R6, R7, R8, _LR); + + // Keep the scale/offset in a few fp registers if we need it. + // This step can be NEON-ized but the savings would be miniscule. + if (prescaleStep) { + MOVI2R(R3, (u32)(&gstate_c.uv), scratchReg); + VLDR(fpUscaleReg, R3, 0); + VLDR(fpVscaleReg, R3, 4); + VLDR(fpUoffsetReg, R3, 8); + VLDR(fpVoffsetReg, R3, 12); + if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { + MOVI2F(fpScratchReg, by128, scratchReg); + VMUL(fpUscaleReg, fpUscaleReg, fpScratchReg); + VMUL(fpVscaleReg, fpVscaleReg, fpScratchReg); + } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { + MOVI2F(fpScratchReg, by32768, scratchReg); + VMUL(fpUscaleReg, fpUscaleReg, fpScratchReg); + VMUL(fpVscaleReg, fpVscaleReg, fpScratchReg); + } + } + + // Add code to convert matrices to 4x4. + // Later we might want to do this when the matrices are loaded instead. + int boneCount = 0; + if (NEONSkinning && dec.weighttype && g_Config.bSoftwareSkinning) { + // Copying from R3 to R4 + MOVP2R(R3, gstate.boneMatrix); + MOVP2R(R4, bones); + MOVI2F(fpScratchReg, 0.0f, scratchReg); + for (int i = 0; i < 8; i++) { + VLD1(F_32, Q4, R3, 2); // Load 128 bits even though we just want 96 + VMOV(S19, fpScratchReg); + ADD(R3, R3, 12); + VLD1(F_32, Q5, R3, 2); + VMOV(S23, fpScratchReg); + ADD(R3, R3, 12); + VLD1(F_32, Q6, R3, 2); + VMOV(S27, fpScratchReg); + ADD(R3, R3, 12); + VLD1(F_32, Q7, R3, 2); + VMOV(S31, fpScratchReg); + ADD(R3, R3, 12); + // First two matrices are in registers. + if (i == 0) { + VMOV(Q8, Q4); + VMOV(Q9, Q5); + VMOV(Q10, Q6); + VMOV(Q11, Q7); + ADD(R4, R4, 16 * 4); + } else if (i == 1) { + VMOV(Q12, Q4); + VMOV(Q13, Q5); + VMOV(Q14, Q6); + VMOV(Q15, Q7); + ADD(R4, R4, 16 * 4); + } else { + VST1(F_32, Q4, R4, 2, ALIGN_128, REG_UPDATE); + VST1(F_32, Q5, R4, 2, ALIGN_128, REG_UPDATE); + VST1(F_32, Q6, R4, 2, ALIGN_128, REG_UPDATE); + VST1(F_32, Q7, R4, 2, ALIGN_128, REG_UPDATE); + } + } + } + + // TODO: NEON skinning register mapping + // The matrix will be built in Q12-Q15. + // The temporary matrix to be added to the built matrix will be in Q8-Q11. + + if (skinning) { + // TODO: Preload scale factors + } + + JumpTarget loopStart = GetCodePtr(); + // Preload data cache ahead of reading. TODO: Experiment with the offset. + PLD(srcReg, 64); + for (int i = 0; i < dec.numSteps_; i++) { + if (!CompileStep(dec, i)) { + // Reset the code ptr and return zero to indicate that we failed. + SetCodePtr(const_cast(start)); + char temp[1024] = {0}; + dec.ToString(temp); + INFO_LOG(HLE, "Could not compile vertex decoder: %s", temp); + return 0; + } + } + + ADDI2R(srcReg, srcReg, dec.VertexSize(), scratchReg); + ADDI2R(dstReg, dstReg, dec.decFmt.stride, scratchReg); + SUBS(counterReg, counterReg, 1); + B_CC(CC_NEQ, loopStart); + + POP(6, R4, R5, R6, R7, R8, _PC); + + FlushLitPool(); + FlushIcache(); + + /* + DisassembleArm(start, GetCodePtr() - start); + char temp[1024] = {0}; + dec.ToString(temp); + INFO_LOG(HLE, "%s", temp); + */ + + return (JittedVertexDecoder)start; +} + +void VertexDecoderJitCache::Jit_WeightsU8() { + // Basic implementation - a byte at a time. TODO: Optimize + int j; + for (j = 0; j < dec_->nweights; j++) { + LDRB(tempReg1, srcReg, dec_->weightoff + j); + STRB(tempReg1, dstReg, dec_->decFmt.w0off + j); + } + if (j & 3) { + // Create a zero register. Might want to make a fixed one. + EOR(scratchReg, scratchReg, scratchReg); + } + while (j & 3) { + STRB(scratchReg, dstReg, dec_->decFmt.w0off + j); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsU16() { + // Basic implementation - a short at a time. TODO: Optimize + int j; + for (j = 0; j < dec_->nweights; j++) { + LDRH(tempReg1, srcReg, dec_->weightoff + j * 2); + STRH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2); + } + if (j & 3) { + // Create a zero register. Might want to make a fixed one. + EOR(scratchReg, scratchReg, scratchReg); + } + while (j & 3) { + STRH(scratchReg, dstReg, dec_->decFmt.w0off + j * 2); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsFloat() { + int j; + for (j = 0; j < dec_->nweights; j++) { + LDR(tempReg1, srcReg, dec_->weightoff + j * 4); + STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); + } + if (j & 3) { + EOR(tempReg1, tempReg1, tempReg1); + } + while (j & 3) { // Zero additional weights rounding up to 4. + STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); + j++; + } +} + +static const ARMReg weightRegs[8] = { S8, S9, S10, S11, S12, S13, S14, S15 }; +static const ARMReg neonWeightRegs[2] = { Q2, Q3 }; + +void VertexDecoderJitCache::Jit_ApplyWeights() { + if (NEONSkinning) { + // We construct a matrix in Q4-Q7 + // We can use Q1 as temp. + if (dec_->nweights >= 2) { + MOVP2R(scratchReg, bones + 16 * 2); + } + for (int i = 0; i < dec_->nweights; i++) { + switch (i) { + case 0: + VMUL_scalar(F_32, Q4, Q8, QScalar(neonWeightRegs[0], 0)); + VMUL_scalar(F_32, Q5, Q9, QScalar(neonWeightRegs[0], 0)); + VMUL_scalar(F_32, Q6, Q10, QScalar(neonWeightRegs[0], 0)); + VMUL_scalar(F_32, Q7, Q11, QScalar(neonWeightRegs[0], 0)); + break; + case 1: + // Krait likes VDUP + VFMA better than VMLA, and it's easy to do here. + if (cpu_info.bVFPv4) { + VDUP(F_32, Q1, neonWeightRegs[i >> 2], i & 1); + VFMA(Q4, Q12, Q1); + VFMA(Q5, Q13, Q1); + VFMA(Q6, Q14, Q1); + VFMA(Q7, Q15, Q1); + } else { + VMLA_scalar(F_32, Q4, Q12, QScalar(neonWeightRegs[0], 1)); + VMLA_scalar(F_32, Q5, Q13, QScalar(neonWeightRegs[0], 1)); + VMLA_scalar(F_32, Q6, Q14, QScalar(neonWeightRegs[0], 1)); + VMLA_scalar(F_32, Q7, Q15, QScalar(neonWeightRegs[0], 1)); + } + break; + default: + // Matrices 2+ need to be loaded from memory. + // Wonder if we can free up one more register so we could get some parallelism. + // Actually Q3 is free if there are fewer than 5 weights... + if (dec_->nweights <= 4) { + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VLD1(F_32, Q3, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q4, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + VMLA_scalar(F_32, Q5, Q3, QScalar(neonWeightRegs[i >> 2], i & 3)); + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VLD1(F_32, Q3, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q6, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + VMLA_scalar(F_32, Q7, Q3, QScalar(neonWeightRegs[i >> 2], i & 3)); + } else { + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q4, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q5, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q6, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + VLD1(F_32, Q1, scratchReg, 2, ALIGN_128, REG_UPDATE); + VMLA_scalar(F_32, Q7, Q1, QScalar(neonWeightRegs[i >> 2], i & 3)); + } + break; + } + } + } else { + MOVI2R(tempReg2, (u32)skinMatrix, scratchReg); + // This approach saves a few stores but accesses the matrices in a more + // sparse order. + const float *bone = &gstate.boneMatrix[0]; + MOVI2R(tempReg1, (u32)bone, scratchReg); + for (int i = 0; i < 12; i++) { + VLDR(fpScratchReg3, tempReg1, i * 4); + VMUL(fpScratchReg3, fpScratchReg3, weightRegs[0]); + for (int j = 1; j < dec_->nweights; j++) { + VLDR(fpScratchReg2, tempReg1, i * 4 + j * 4 * 12); + VMLA(fpScratchReg3, fpScratchReg2, weightRegs[j]); + } + VSTR(fpScratchReg3, tempReg2, i * 4); + } + } +} + +void VertexDecoderJitCache::Jit_WeightsU8Skin() { + if (NEONSkinning && dec_->nweights <= 4) { + // Most common cases. + // Weight is first so srcReg is correct. + switch (dec_->nweights) { + case 1: LDRB(scratchReg2, srcReg, 0); break; + case 2: LDRH(scratchReg2, srcReg, 0); break; + case 3: + LDR(scratchReg2, srcReg, 0); + ANDI2R(scratchReg2, scratchReg2, 0xFFFFFF, scratchReg); + break; + case 4: + LDR(scratchReg2, srcReg, 0); + break; + } + VMOV(fpScratchReg, scratchReg2); + MOVI2F(S12, by128, scratchReg); + VMOVL(I_8 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); + VMOVL(I_16 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); + VCVT(F_32 | I_UNSIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, neonWeightRegs[0], neonScratchRegQ, DScalar(D6, 0)); + } else { + // Fallback and non-neon + for (int j = 0; j < dec_->nweights; j++) { + LDRB(tempReg1, srcReg, dec_->weightoff + j); + VMOV(fpScratchReg, tempReg1); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); + MOVI2F(fpScratchReg2, by128, scratchReg); + VMUL(weightRegs[j], fpScratchReg, fpScratchReg2); + } + } + Jit_ApplyWeights(); +} + +void VertexDecoderJitCache::Jit_WeightsU16Skin() { + if (NEONSkinning && dec_->nweights <= 4) { + // Most common cases. + switch (dec_->nweights) { + case 1: LDRH(scratchReg, srcReg, 0); break; + case 2: LDR(scratchReg, srcReg, 0); break; + case 3: + LDR(scratchReg, srcReg, 0); + LDRH(scratchReg2, srcReg, 4); + break; + case 4: + LDR(scratchReg, srcReg, 0); + LDR(scratchReg2, srcReg, 4); + break; + } + VMOV(fpScratchReg, scratchReg); + VMOV(fpScratchReg2, scratchReg2); + MOVI2F(S12, by32768, scratchReg); + VMOVL(I_16 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); + VCVT(F_32 | I_UNSIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, neonWeightRegs[0], neonScratchRegQ, DScalar(D6, 0)); + } else { + // Fallback and non-neon + for (int j = 0; j < dec_->nweights; j++) { + LDRH(tempReg1, srcReg, dec_->weightoff + j * 2); + VMOV(fpScratchReg, tempReg1); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); + MOVI2F(fpScratchReg2, 1.0f / 32768.0f, scratchReg); + VMUL(weightRegs[j], fpScratchReg, fpScratchReg2); + } + } + Jit_ApplyWeights(); +} + +void VertexDecoderJitCache::Jit_WeightsFloatSkin() { + // TODO: NEON-ize (barely worth) + for (int j = 0; j < dec_->nweights; j++) { + VLDR(weightRegs[j], srcReg, dec_->weightoff + j * 4); + } + Jit_ApplyWeights(); +} + +// Fill last two bytes with zeroes to align to 4 bytes. LDRH does it for us, handy. +void VertexDecoderJitCache::Jit_TcU8() { + LDRB(tempReg1, srcReg, dec_->tcoff); + LDRB(tempReg2, srcReg, dec_->tcoff + 1); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); +} + +void VertexDecoderJitCache::Jit_TcU16() { + LDRH(tempReg1, srcReg, dec_->tcoff); + LDRH(tempReg2, srcReg, dec_->tcoff + 2); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); +} + +void VertexDecoderJitCache::Jit_TcFloat() { + LDR(tempReg1, srcReg, dec_->tcoff); + LDR(tempReg2, srcReg, dec_->tcoff + 4); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); + STR(tempReg2, dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16Through() { + LDRH(tempReg1, srcReg, dec_->tcoff); + LDRH(tempReg2, srcReg, dec_->tcoff + 2); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); +} + +void VertexDecoderJitCache::Jit_TcFloatThrough() { + LDR(tempReg1, srcReg, dec_->tcoff); + LDR(tempReg2, srcReg, dec_->tcoff + 4); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); + STR(tempReg2, dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16Double() { + LDRH(tempReg1, srcReg, dec_->tcoff); + LDRH(tempReg2, srcReg, dec_->tcoff + 2); + LSL(tempReg1, tempReg1, 1); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 17)); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); +} + +void VertexDecoderJitCache::Jit_TcU16ThroughDouble() { + LDRH(tempReg1, srcReg, dec_->tcoff); + LDRH(tempReg2, srcReg, dec_->tcoff + 2); + LSL(tempReg1, tempReg1, 1); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 17)); + STR(tempReg1, dstReg, dec_->decFmt.uvoff); +} + +void VertexDecoderJitCache::Jit_TcU8Prescale() { + if (cpu_info.bNEON) { + // TODO: Needs testing + ADD(scratchReg, srcReg, dec_->tcoff); + VLD1_lane(I_16, neonScratchReg, scratchReg, 0, false); + VMOVL(I_8 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); // Widen to 16-bit + VMOVL(I_16 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_UNSIGNED, neonScratchRegQ, neonScratchRegQ); + ADD(scratchReg2, dstReg, dec_->decFmt.uvoff); + VMUL(F_32, neonScratchReg, neonScratchReg, neonUVScaleReg); + VADD(F_32, neonScratchReg, neonScratchReg, neonUVOffsetReg); + VST1(F_32, neonScratchReg, scratchReg2, 1, ALIGN_NONE); + } else { + // TODO: SIMD + LDRB(tempReg1, srcReg, dec_->tcoff); + LDRB(tempReg2, srcReg, dec_->tcoff + 1); + VMOV(fpScratchReg, tempReg1); + VMOV(fpScratchReg2, tempReg2); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); + VCVT(fpScratchReg2, fpScratchReg2, TO_FLOAT); + // Could replace VMUL + VADD with VMLA but would require 2 more regs as we don't want to destroy fp*offsetReg. Later. + VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); + VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); + VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); + VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); + VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); + VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); + } +} + +void VertexDecoderJitCache::Jit_TcU16Prescale() { + if (cpu_info.bNEON) { + // TODO: Needs testing + ADD(scratchReg, srcReg, dec_->tcoff); + VLD1_lane(I_32, neonScratchReg, scratchReg, 0, false); + VMOVL(I_16 | I_UNSIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_UNSIGNED, neonScratchRegQ, neonScratchRegQ); + ADD(scratchReg2, dstReg, dec_->decFmt.uvoff); + VMUL(F_32, neonScratchReg, neonScratchReg, neonUVScaleReg); + VADD(F_32, neonScratchReg, neonScratchReg, neonUVOffsetReg); + VST1(F_32, neonScratchReg, scratchReg2, 1, ALIGN_NONE); + } else { + LDRH(tempReg1, srcReg, dec_->tcoff); + LDRH(tempReg2, srcReg, dec_->tcoff + 2); + VMOV(fpScratchReg, tempReg1); + VMOV(fpScratchReg2, tempReg2); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT); + VCVT(fpScratchReg2, fpScratchReg2, TO_FLOAT); + VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); + VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); + VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); + VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); + VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); + VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); + } +} + +void VertexDecoderJitCache::Jit_TcFloatPrescale() { + if (cpu_info.bNEON) { + ADD(scratchReg, srcReg, dec_->tcoff); + VLD1(F_32, neonScratchReg, scratchReg, 1, ALIGN_NONE); + ADD(scratchReg2, dstReg, dec_->decFmt.uvoff); + VMUL(F_32, neonScratchReg, neonScratchReg, neonUVScaleReg); + VADD(F_32, neonScratchReg, neonScratchReg, neonUVOffsetReg); + VST1(F_32, neonScratchReg, scratchReg2, 1, ALIGN_NONE); + } else { + // TODO: SIMD + VLDR(fpScratchReg, srcReg, dec_->tcoff); + VLDR(fpScratchReg2, srcReg, dec_->tcoff + 4); + VMUL(fpScratchReg, fpScratchReg, fpUscaleReg); + VMUL(fpScratchReg2, fpScratchReg2, fpVscaleReg); + VADD(fpScratchReg, fpScratchReg, fpUoffsetReg); + VADD(fpScratchReg2, fpScratchReg2, fpVoffsetReg); + VSTR(fpScratchReg, dstReg, dec_->decFmt.uvoff); + VSTR(fpScratchReg2, dstReg, dec_->decFmt.uvoff + 4); + } +} + +void VertexDecoderJitCache::Jit_Color8888() { + LDR(tempReg1, srcReg, dec_->coloff); + STR(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color4444() { + LDRH(tempReg1, srcReg, dec_->coloff); + + // Spread out the components. + ANDI2R(tempReg2, tempReg1, 0x000F, scratchReg); + ANDI2R(tempReg3, tempReg1, 0x00F0, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 4)); + ANDI2R(tempReg3, tempReg1, 0x0F00, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 8)); + ANDI2R(tempReg3, tempReg1, 0xF000, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 12)); + + // And saturate. + ORR(tempReg1, tempReg2, Operand2(tempReg2, ST_LSL, 4)); + + STR(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color565() { + LDRH(tempReg1, srcReg, dec_->coloff); + + // Spread out R and B first. This puts them in 0x001F001F. + ANDI2R(tempReg2, tempReg1, 0x001F, scratchReg); + ANDI2R(tempReg3, tempReg1, 0xF800, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 5)); + + // Expand 5 -> 8. + LSL(tempReg3, tempReg2, 3); + ORR(tempReg2, tempReg3, Operand2(tempReg2, ST_LSR, 2)); + ANDI2R(tempReg2, tempReg2, 0xFFFF00FF, scratchReg); + + // Now finally G. We start by shoving it into a wall. + LSR(tempReg1, tempReg1, 5); + ANDI2R(tempReg1, tempReg1, 0x003F, scratchReg); + LSL(tempReg3, tempReg1, 2); + // Don't worry, shifts into a wall. + ORR(tempReg3, tempReg3, Operand2(tempReg1, ST_LSR, 4)); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 8)); + + // Add in full alpha. + ORI2R(tempReg1, tempReg2, 0xFF000000, scratchReg); + + STR(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color5551() { + LDRH(tempReg1, srcReg, dec_->coloff); + + ANDI2R(tempReg2, tempReg1, 0x001F, scratchReg); + ANDI2R(tempReg3, tempReg1, 0x07E0, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 3)); + ANDI2R(tempReg3, tempReg1, 0xF800, scratchReg); + ORR(tempReg2, tempReg2, Operand2(tempReg3, ST_LSL, 6)); + + // Expand 5 -> 8. + LSR(tempReg3, tempReg2, 2); + // Clean up the bits that were shifted right. + BIC(tempReg3, tempReg1, AssumeMakeOperand2(0x000000F8)); + BIC(tempReg3, tempReg3, AssumeMakeOperand2(0x0000F800)); + ORR(tempReg2, tempReg3, Operand2(tempReg2, ST_LSL, 3)); + + // Now we just need alpha. + TSTI2R(tempReg1, 0x8000, scratchReg); + SetCC(CC_NEQ); + ORI2R(tempReg2, tempReg2, 0xFF000000, scratchReg); + SetCC(CC_AL); + + STR(tempReg2, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_NormalS8() { + LDRB(tempReg1, srcReg, dec_->nrmoff); + LDRB(tempReg2, srcReg, dec_->nrmoff + 1); + LDRB(tempReg3, srcReg, dec_->nrmoff + 2); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); + ORR(tempReg1, tempReg1, Operand2(tempReg3, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.nrmoff); + + // Copy 3 bytes and then a zero. Might as well copy four. + // LDR(tempReg1, srcReg, dec_->nrmoff); + // ANDI2R(tempReg1, tempReg1, 0x00FFFFFF, scratchReg); + // STR(tempReg1, dstReg, dec_->decFmt.nrmoff); +} + +// Copy 6 bytes and then 2 zeroes. +void VertexDecoderJitCache::Jit_NormalS16() { + LDRH(tempReg1, srcReg, dec_->nrmoff); + LDRH(tempReg2, srcReg, dec_->nrmoff + 2); + LDRH(tempReg3, srcReg, dec_->nrmoff + 4); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.nrmoff); + STR(tempReg3, dstReg, dec_->decFmt.nrmoff + 4); +} + +void VertexDecoderJitCache::Jit_NormalFloat() { + // Might not be aligned to 4, so we can't use LDMIA. + // Actually - not true: This will always be aligned. TODO + LDR(tempReg1, srcReg, dec_->nrmoff); + LDR(tempReg2, srcReg, dec_->nrmoff + 4); + LDR(tempReg3, srcReg, dec_->nrmoff + 8); + // But this is always aligned to 4 so we're safe. + ADD(scratchReg, dstReg, dec_->decFmt.nrmoff); + STMIA(scratchReg, false, 3, tempReg1, tempReg2, tempReg3); +} + +// Through expands into floats, always. Might want to look at changing this. +void VertexDecoderJitCache::Jit_PosS8Through() { + // TODO: SIMD + LDRSB(tempReg1, srcReg, dec_->posoff); + LDRSB(tempReg2, srcReg, dec_->posoff + 1); + LDRSB(tempReg3, srcReg, dec_->posoff + 2); + static const ARMReg tr[3] = { tempReg1, tempReg2, tempReg3 }; + for (int i = 0; i < 3; i++) { + VMOV(fpScratchReg, tr[i]); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT | IS_SIGNED); + VSTR(fpScratchReg, dstReg, dec_->decFmt.posoff + i * 4); + } +} + +// Through expands into floats, always. Might want to look at changing this. +void VertexDecoderJitCache::Jit_PosS16Through() { + // TODO: SIMD + LDRSH(tempReg1, srcReg, dec_->posoff); + LDRSH(tempReg2, srcReg, dec_->posoff + 2); + LDRSH(tempReg3, srcReg, dec_->posoff + 4); + static const ARMReg tr[3] = { tempReg1, tempReg2, tempReg3 }; + for (int i = 0; i < 3; i++) { + VMOV(fpScratchReg, tr[i]); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT | IS_SIGNED); + VSTR(fpScratchReg, dstReg, dec_->decFmt.posoff + i * 4); + } +} + +// Copy 3 bytes and then a zero. Might as well copy four. +void VertexDecoderJitCache::Jit_PosS8() { + LDRB(tempReg1, srcReg, dec_->posoff); + LDRB(tempReg2, srcReg, dec_->posoff + 1); + LDRB(tempReg3, srcReg, dec_->posoff + 2); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8)); + ORR(tempReg1, tempReg1, Operand2(tempReg3, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.posoff); +} + +// Copy 6 bytes and then 2 zeroes. +void VertexDecoderJitCache::Jit_PosS16() { + LDRH(tempReg1, srcReg, dec_->posoff); + LDRH(tempReg2, srcReg, dec_->posoff + 2); + LDRH(tempReg3, srcReg, dec_->posoff + 4); + ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16)); + STR(tempReg1, dstReg, dec_->decFmt.posoff); + STR(tempReg3, dstReg, dec_->decFmt.posoff + 4); +} + +// Just copy 12 bytes. +void VertexDecoderJitCache::Jit_PosFloat() { + LDR(tempReg1, srcReg, dec_->posoff); + LDR(tempReg2, srcReg, dec_->posoff + 4); + LDR(tempReg3, srcReg, dec_->posoff + 8); + // But this is always aligned to 4 so we're safe. + ADD(scratchReg, dstReg, dec_->decFmt.posoff); + STMIA(scratchReg, false, 3, tempReg1, tempReg2, tempReg3); +} + +void VertexDecoderJitCache::Jit_NormalS8Skin() { + if (NEONSkinning) { + ADD(scratchReg, srcReg, dec_->nrmoff); + VLD1_lane(I_32, neonScratchReg, scratchReg, 0, false); + MOVI2F(S15, 1.0f/128.0f, scratchReg); + VMOVL(I_8 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 16-bit + VMOVL(I_16 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_SIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, srcNEON, neonScratchReg, QScalar(Q3, 3)); // S15 + } else { + LDRSB(tempReg1, srcReg, dec_->nrmoff); + LDRSB(tempReg2, srcReg, dec_->nrmoff + 1); + LDRSB(tempReg3, srcReg, dec_->nrmoff + 2); + VMOV(src[0], tempReg1); + VMOV(src[1], tempReg2); + VMOV(src[2], tempReg3); + MOVI2F(S15, 1.0f/128.0f, scratchReg); + VCVT(src[0], src[0], TO_FLOAT | IS_SIGNED); + VCVT(src[1], src[1], TO_FLOAT | IS_SIGNED); + VCVT(src[2], src[2], TO_FLOAT | IS_SIGNED); + VMUL(src[0], src[0], S15); + VMUL(src[1], src[1], S15); + VMUL(src[2], src[2], S15); + } + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalS16Skin() { + if (NEONSkinning) { + ADD(scratchReg, srcReg, dec_->nrmoff); + VLD1(I_32, neonScratchReg, scratchReg, 1, ALIGN_NONE); + MOVI2F(S15, 1.0f/32768, scratchReg); + VMOVL(I_16 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_SIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, srcNEON, neonScratchReg, QScalar(Q3, 3)); // S15 + } else { + LDRSH(tempReg1, srcReg, dec_->nrmoff); + LDRSH(tempReg2, srcReg, dec_->nrmoff + 2); + LDRSH(tempReg3, srcReg, dec_->nrmoff + 4); + VMOV(fpScratchReg, tempReg1); + VMOV(fpScratchReg2, tempReg2); + VMOV(fpScratchReg3, tempReg3); + MOVI2F(S15, 1.0f/32768.0f, scratchReg); + VCVT(fpScratchReg, fpScratchReg, TO_FLOAT | IS_SIGNED); + VCVT(fpScratchReg2, fpScratchReg2, TO_FLOAT | IS_SIGNED); + VCVT(fpScratchReg3, fpScratchReg3, TO_FLOAT | IS_SIGNED); + VMUL(src[0], fpScratchReg, S15); + VMUL(src[1], fpScratchReg2, S15); + VMUL(src[2], fpScratchReg3, S15); + } + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalFloatSkin() { + VLDR(src[0], srcReg, dec_->nrmoff); + VLDR(src[1], srcReg, dec_->nrmoff + 4); + VLDR(src[2], srcReg, dec_->nrmoff + 8); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_WriteMatrixMul(int outOff, bool pos) { + if (NEONSkinning) { + // Multiply with the matrix sitting in Q4-Q7. + ADD(scratchReg, dstReg, outOff); + VMUL_scalar(F_32, accNEON, Q4, QScalar(srcNEON, 0)); + VMLA_scalar(F_32, accNEON, Q5, QScalar(srcNEON, 1)); + VMLA_scalar(F_32, accNEON, Q6, QScalar(srcNEON, 2)); + if (pos) { + VADD(F_32, accNEON, accNEON, Q7); + } + VST1(F_32, accNEON, scratchReg, 2); + } else { + MOVI2R(tempReg1, (u32)skinMatrix, scratchReg); + for (int i = 0; i < 3; i++) { + VLDR(fpScratchReg, tempReg1, 4 * i); + VMUL(acc[i], fpScratchReg, src[0]); + } + for (int i = 0; i < 3; i++) { + VLDR(fpScratchReg, tempReg1, 12 + 4 * i); + VMLA(acc[i], fpScratchReg, src[1]); + } + for (int i = 0; i < 3; i++) { + VLDR(fpScratchReg, tempReg1, 24 + 4 * i); + VMLA(acc[i], fpScratchReg, src[2]); + } + if (pos) { + for (int i = 0; i < 3; i++) { + VLDR(fpScratchReg, tempReg1, 36 + 4 * i); + VADD(acc[i], acc[i], fpScratchReg); + } + } + for (int i = 0; i < 3; i++) { + VSTR(acc[i], dstReg, outOff + i * 4); + } + } +} + +void VertexDecoderJitCache::Jit_PosS8Skin() { + if (NEONSkinning) { + ADD(scratchReg, srcReg, dec_->posoff); + VLD1_lane(I_32, neonScratchReg, scratchReg, 0, false); + MOVI2F(S15, 1.0f/128.0f, scratchReg); + VMOVL(I_8 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 16-bit + VMOVL(I_16 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_SIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, srcNEON, neonScratchReg, QScalar(Q3, 3)); // S15 + } else { + LDRSB(tempReg1, srcReg, dec_->posoff); + LDRSB(tempReg2, srcReg, dec_->posoff + 1); + LDRSB(tempReg3, srcReg, dec_->posoff + 2); + VMOV(src[0], tempReg1); + VMOV(src[1], tempReg2); + VMOV(src[2], tempReg3); + MOVI2F(S15, 1.0f/128.0f, scratchReg); + VCVT(src[0], src[0], TO_FLOAT | IS_SIGNED); + VCVT(src[1], src[1], TO_FLOAT | IS_SIGNED); + VCVT(src[2], src[2], TO_FLOAT | IS_SIGNED); + VMUL(src[0], src[0], S15); + VMUL(src[1], src[1], S15); + VMUL(src[2], src[2], S15); + } + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +void VertexDecoderJitCache::Jit_PosS16Skin() { + if (NEONSkinning) { + ADD(scratchReg, srcReg, dec_->posoff); + VLD1(I_32, neonScratchReg, scratchReg, 1, ALIGN_NONE); + MOVI2F(S15, 1.0f/32768, scratchReg); + VMOVL(I_16 | I_SIGNED, neonScratchRegQ, neonScratchReg); // Widen to 32-bit + VCVT(F_32 | I_SIGNED, neonScratchRegQ, neonScratchRegQ); + VMUL_scalar(F_32, srcNEON, neonScratchReg, QScalar(Q3, 3)); // S15 + } else { + LDRSH(tempReg1, srcReg, dec_->posoff); + LDRSH(tempReg2, srcReg, dec_->posoff + 2); + LDRSH(tempReg3, srcReg, dec_->posoff + 4); + VMOV(src[0], tempReg1); + VMOV(src[1], tempReg2); + VMOV(src[2], tempReg3); + MOVI2F(S15, 1.0f/32768.0f, scratchReg); + VCVT(src[0], src[0], TO_FLOAT | IS_SIGNED); + VCVT(src[1], src[1], TO_FLOAT | IS_SIGNED); + VCVT(src[2], src[2], TO_FLOAT | IS_SIGNED); + VMUL(src[0], src[0], S15); + VMUL(src[1], src[1], S15); + VMUL(src[2], src[2], S15); + } + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +void VertexDecoderJitCache::Jit_PosFloatSkin() { + VLDR(src[0], srcReg, dec_->posoff); + VLDR(src[1], srcReg, dec_->posoff + 4); + VLDR(src[2], srcReg, dec_->posoff + 8); + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { + // See if we find a matching JIT function + for (size_t i = 0; i < ARRAY_SIZE(jitLookup); i++) { + if (dec.steps_[step] == jitLookup[i].func) { + ((*this).*jitLookup[i].jitFunc)(); + return true; + } + } + return false; +} diff --git a/GPU/GLES/VertexDecoderX86.cpp b/GPU/GLES/VertexDecoderX86.cpp new file mode 100644 index 0000000000..c76ee4ab48 --- /dev/null +++ b/GPU/GLES/VertexDecoderX86.cpp @@ -0,0 +1,840 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include + +#include "Common/CPUDetect.h" +#include "Core/Config.h" +#include "GPU/GLES/VertexDecoder.h" + +// We start out by converting the active matrices into 4x4 which are easier to multiply with +// using SSE / NEON and store them here. +static float MEMORY_ALIGNED16(bones[16 * 8]); + +using namespace Gen; + +static const float MEMORY_ALIGNED16( by128[4] ) = { + 1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f +}; +static const float MEMORY_ALIGNED16( by256[4] ) = { + 1.0f / 256, 1.0f / 256, 1.0f / 256, 1.0f / 256 +}; +static const float MEMORY_ALIGNED16( by32768[4] ) = { + 1.0f / 32768.0f, 1.0f / 32768.0f, 1.0f / 32768.0f, 1.0f / 32768.0f, +}; + +static const u32 MEMORY_ALIGNED16( threeMasks[4] ) = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0}; +static const u32 MEMORY_ALIGNED16( aOne[4] ) = {0, 0, 0, 0x3F800000}; + +#ifdef _M_X64 +#ifdef _WIN32 +static const X64Reg tempReg1 = RAX; +static const X64Reg tempReg2 = R9; +static const X64Reg tempReg3 = R10; +static const X64Reg srcReg = RCX; +static const X64Reg dstReg = RDX; +static const X64Reg counterReg = R8; +#else +static const X64Reg tempReg1 = RAX; +static const X64Reg tempReg2 = R9; +static const X64Reg tempReg3 = R10; +static const X64Reg srcReg = RDI; +static const X64Reg dstReg = RSI; +static const X64Reg counterReg = RDX; +#endif +#else +static const X64Reg tempReg1 = EAX; +static const X64Reg tempReg2 = EBX; +static const X64Reg tempReg3 = EDX; +static const X64Reg srcReg = ESI; +static const X64Reg dstReg = EDI; +static const X64Reg counterReg = ECX; +#endif + +// XMM0-XMM5 are volatile on Windows X64 +// XMM0-XMM7 are arguments (and thus volatile) on System V ABI (other x64 platforms) +static const X64Reg fpScaleOffsetReg = XMM0; + +static const X64Reg fpScratchReg = XMM1; +static const X64Reg fpScratchReg2 = XMM2; +static const X64Reg fpScratchReg3 = XMM3; + +// We're gonna keep the current skinning matrix in 4 XMM regs. Fortunately we easily +// have space for that now. + +// To debug, just comment them out one at a time until it works. We fall back +// on the interpreter if the compiler fails. + +static const JitLookup jitLookup[] = { + {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, + {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, + {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, + + {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, + {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, + {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, + + {&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8}, + {&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16}, + {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, + {&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double}, + + {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, + {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, + {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, + + {&VertexDecoder::Step_TcU16Through, &VertexDecoderJitCache::Jit_TcU16Through}, + {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, + {&VertexDecoder::Step_TcU16ThroughDouble, &VertexDecoderJitCache::Jit_TcU16ThroughDouble}, + + {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, + {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, + {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, + + {&VertexDecoder::Step_NormalS8Skin, &VertexDecoderJitCache::Jit_NormalS8Skin}, + {&VertexDecoder::Step_NormalS16Skin, &VertexDecoderJitCache::Jit_NormalS16Skin}, + {&VertexDecoder::Step_NormalFloatSkin, &VertexDecoderJitCache::Jit_NormalFloatSkin}, + + {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, + {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, + {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, + {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, + + {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, + {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, + {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloat}, + + {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, + {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, + {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, + + {&VertexDecoder::Step_PosS8Skin, &VertexDecoderJitCache::Jit_PosS8Skin}, + {&VertexDecoder::Step_PosS16Skin, &VertexDecoderJitCache::Jit_PosS16Skin}, + {&VertexDecoder::Step_PosFloatSkin, &VertexDecoderJitCache::Jit_PosFloatSkin}, +}; + +// TODO: This should probably be global... +#ifdef _M_X64 +#define PTRBITS 64 +#else +#define PTRBITS 32 +#endif + +JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec) { + dec_ = &dec; + const u8 *start = this->GetCodePtr(); + +#ifdef _M_IX86 + // Store register values + PUSH(ESI); + PUSH(EDI); + PUSH(EBX); + PUSH(EBP); + + // Read parameters + int offset = 4; + MOV(32, R(srcReg), MDisp(ESP, 16 + offset + 0)); + MOV(32, R(dstReg), MDisp(ESP, 16 + offset + 4)); + MOV(32, R(counterReg), MDisp(ESP, 16 + offset + 8)); +#endif + + // Save XMM4/XMM5 which apparently can be problematic? + // Actually, if they are, it must be a compiler bug because they SHOULD be ok. + // So I won't bother. + SUB(PTRBITS, R(ESP), Imm8(64)); + MOVUPS(MDisp(ESP, 0), XMM4); + MOVUPS(MDisp(ESP, 16), XMM5); + MOVUPS(MDisp(ESP, 32), XMM6); + MOVUPS(MDisp(ESP, 48), XMM7); + + bool prescaleStep = false; + // Look for prescaled texcoord steps + for (int i = 0; i < dec.numSteps_; i++) { + if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { + prescaleStep = true; + } + } + + // Add code to convert matrices to 4x4. + // Later we might want to do this when the matrices are loaded instead. + // This is mostly proof of concept. + int boneCount = 0; + if (dec.weighttype && g_Config.bSoftwareSkinning) { + for (int i = 0; i < 8; i++) { + MOVUPS(XMM0, M((void *)(gstate.boneMatrix + 12 * i))); + MOVUPS(XMM1, M((void *)(gstate.boneMatrix + 12 * i + 3))); + MOVUPS(XMM2, M((void *)(gstate.boneMatrix + 12 * i + 3 * 2))); + MOVUPS(XMM3, M((void *)(gstate.boneMatrix + 12 * i + 3 * 3))); + ANDPS(XMM0, M((void *)&threeMasks)); + ANDPS(XMM1, M((void *)&threeMasks)); + ANDPS(XMM2, M((void *)&threeMasks)); + ANDPS(XMM3, M((void *)&threeMasks)); + ORPS(XMM3, M((void *)&aOne)); + MOVAPS(M((void *)(bones + 16 * i)), XMM0); + MOVAPS(M((void *)(bones + 16 * i + 4)), XMM1); + MOVAPS(M((void *)(bones + 16 * i + 8)), XMM2); + MOVAPS(M((void *)(bones + 16 * i + 12)), XMM3); + } + } + + // Keep the scale/offset in a few fp registers if we need it. + if (prescaleStep) { +#ifdef _M_X64 + MOV(64, R(tempReg1), Imm64((u64)(&gstate_c.uv))); +#else + MOV(32, R(tempReg1), Imm32((u32)(&gstate_c.uv))); +#endif + MOVSS(fpScaleOffsetReg, MDisp(tempReg1, 0)); + MOVSS(fpScratchReg, MDisp(tempReg1, 4)); + UNPCKLPS(fpScaleOffsetReg, R(fpScratchReg)); + if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { + MULPS(fpScaleOffsetReg, M((void *)&by128)); + } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { + MULPS(fpScaleOffsetReg, M((void *)&by32768)); + } + MOVSS(fpScratchReg, MDisp(tempReg1, 8)); + MOVSS(fpScratchReg2, MDisp(tempReg1, 12)); + UNPCKLPS(fpScratchReg, R(fpScratchReg2)); + UNPCKLPD(fpScaleOffsetReg, R(fpScratchReg)); + } + + // Let's not bother with a proper stack frame. We just grab the arguments and go. + JumpTarget loopStart = GetCodePtr(); + for (int i = 0; i < dec.numSteps_; i++) { + if (!CompileStep(dec, i)) { + // Reset the code ptr and return zero to indicate that we failed. + SetCodePtr(const_cast(start)); + return 0; + } + } + + ADD(PTRBITS, R(srcReg), Imm32(dec.VertexSize())); + ADD(PTRBITS, R(dstReg), Imm32(dec.decFmt.stride)); + SUB(32, R(counterReg), Imm8(1)); + J_CC(CC_NZ, loopStart, true); + + MOVUPS(XMM4, MDisp(ESP, 0)); + MOVUPS(XMM5, MDisp(ESP, 16)); + MOVUPS(XMM6, MDisp(ESP, 32)); + MOVUPS(XMM7, MDisp(ESP, 48)); + ADD(PTRBITS, R(ESP), Imm8(64)); + +#ifdef _M_IX86 + // Restore register values + POP(EBP); + POP(EBX); + POP(EDI); + POP(ESI); +#endif + + RET(); + + return (JittedVertexDecoder)start; +} + +void VertexDecoderJitCache::Jit_WeightsU8() { + switch (dec_->nweights) { + case 1: + MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->weightoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + return; + case 2: + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + return; + case 3: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + AND(32, R(tempReg1), Imm32(0x00FFFFFF)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + return; + case 4: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + return; + case 8: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.w1off), R(tempReg2)); + return; + } + + // Basic implementation - a byte at a time. TODO: Optimize + int j; + for (j = 0; j < dec_->nweights; j++) { + MOV(8, R(tempReg1), MDisp(srcReg, dec_->weightoff + j)); + MOV(8, MDisp(dstReg, dec_->decFmt.w0off + j), R(tempReg1)); + } + while (j & 3) { + MOV(8, MDisp(dstReg, dec_->decFmt.w0off + j), Imm8(0)); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsU16() { + switch (dec_->nweights) { + case 1: + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0)); + return; + + case 2: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0)); + return; + + case 3: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->weightoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2)); + return; + + case 4: + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2)); + return; + } + + // Basic implementation - a short at a time. TODO: Optimize + int j; + for (j = 0; j < dec_->nweights; j++) { + MOV(16, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 2)); + MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), R(tempReg1)); + } + while (j & 3) { + MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), Imm16(0)); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsFloat() { + int j; + for (j = 0; j < dec_->nweights; j++) { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), R(tempReg1)); + } + while (j & 3) { // Zero additional weights rounding up to 4. + MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), Imm32(0)); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsU8Skin() { +#ifdef _M_X64 + MOV(PTRBITS, R(tempReg2), Imm64((uintptr_t)&bones)); +#else + MOV(PTRBITS, R(tempReg2), Imm32((uintptr_t)&bones)); +#endif + for (int j = 0; j < dec_->nweights; j++) { + MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->weightoff + j)); + CVTSI2SS(XMM1, R(tempReg1)); + MULSS(XMM1, M((void *)&by128)); + SHUFPS(XMM1, R(XMM1), _MM_SHUFFLE(0, 0, 0, 0)); + if (j == 0) { + MOVAPS(XMM4, MDisp(tempReg2, 0)); + MOVAPS(XMM5, MDisp(tempReg2, 16)); + MOVAPS(XMM6, MDisp(tempReg2, 32)); + MOVAPS(XMM7, MDisp(tempReg2, 48)); + MULPS(XMM4, R(XMM1)); + MULPS(XMM5, R(XMM1)); + MULPS(XMM6, R(XMM1)); + MULPS(XMM7, R(XMM1)); + } else { + MOVAPS(XMM2, MDisp(tempReg2, 0)); + MOVAPS(XMM3, MDisp(tempReg2, 16)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM4, R(XMM2)); + ADDPS(XMM5, R(XMM3)); + MOVAPS(XMM2, MDisp(tempReg2, 32)); + MOVAPS(XMM3, MDisp(tempReg2, 48)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM6, R(XMM2)); + ADDPS(XMM7, R(XMM3)); + } + ADD(PTRBITS, R(tempReg2), Imm8(4 * 16)); + } +} + +void VertexDecoderJitCache::Jit_WeightsU16Skin() { +#ifdef _M_X64 + MOV(PTRBITS, R(tempReg2), Imm64((uintptr_t)&bones)); +#else + MOV(PTRBITS, R(tempReg2), Imm32((uintptr_t)&bones)); +#endif + for (int j = 0; j < dec_->nweights; j++) { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff + j * 2)); + CVTSI2SS(XMM1, R(tempReg1)); + MULSS(XMM1, M((void *)&by32768)); + SHUFPS(XMM1, R(XMM1), _MM_SHUFFLE(0, 0, 0, 0)); + if (j == 0) { + MOVAPS(XMM4, MDisp(tempReg2, 0)); + MOVAPS(XMM5, MDisp(tempReg2, 16)); + MOVAPS(XMM6, MDisp(tempReg2, 32)); + MOVAPS(XMM7, MDisp(tempReg2, 48)); + MULPS(XMM4, R(XMM1)); + MULPS(XMM5, R(XMM1)); + MULPS(XMM6, R(XMM1)); + MULPS(XMM7, R(XMM1)); + } else { + MOVAPS(XMM2, MDisp(tempReg2, 0)); + MOVAPS(XMM3, MDisp(tempReg2, 16)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM4, R(XMM2)); + ADDPS(XMM5, R(XMM3)); + MOVAPS(XMM2, MDisp(tempReg2, 32)); + MOVAPS(XMM3, MDisp(tempReg2, 48)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM6, R(XMM2)); + ADDPS(XMM7, R(XMM3)); + } + ADD(PTRBITS, R(tempReg2), Imm8(4 * 16)); + } +} + +void VertexDecoderJitCache::Jit_WeightsFloatSkin() { +#ifdef _M_X64 + MOV(PTRBITS, R(tempReg2), Imm64((uintptr_t)&bones)); +#else + MOV(PTRBITS, R(tempReg2), Imm32((uintptr_t)&bones)); +#endif + for (int j = 0; j < dec_->nweights; j++) { + MOVSS(XMM1, MDisp(srcReg, dec_->weightoff + j * 4)); + SHUFPS(XMM1, R(XMM1), _MM_SHUFFLE(0, 0, 0, 0)); + if (j == 0) { + MOVAPS(XMM4, MDisp(tempReg2, 0)); + MOVAPS(XMM5, MDisp(tempReg2, 16)); + MOVAPS(XMM6, MDisp(tempReg2, 32)); + MOVAPS(XMM7, MDisp(tempReg2, 48)); + MULPS(XMM4, R(XMM1)); + MULPS(XMM5, R(XMM1)); + MULPS(XMM6, R(XMM1)); + MULPS(XMM7, R(XMM1)); + } else { + MOVAPS(XMM2, MDisp(tempReg2, 0)); + MOVAPS(XMM3, MDisp(tempReg2, 16)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM4, R(XMM2)); + ADDPS(XMM5, R(XMM3)); + MOVAPS(XMM2, MDisp(tempReg2, 32)); + MOVAPS(XMM3, MDisp(tempReg2, 48)); + MULPS(XMM2, R(XMM1)); + MULPS(XMM3, R(XMM1)); + ADDPS(XMM6, R(XMM2)); + ADDPS(XMM7, R(XMM3)); + } + ADD(PTRBITS, R(tempReg2), Imm8(4 * 16)); + } +} + +// Fill last two bytes with zeroes to align to 4 bytes. MOVZX does it for us, handy. +void VertexDecoderJitCache::Jit_TcU8() { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +} + +void VertexDecoderJitCache::Jit_TcU16() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +} + +void VertexDecoderJitCache::Jit_TcU16Double() { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); + MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->tcoff + 2)); + SHL(16, R(tempReg1), Imm8(1)); // 16 to get a wall to shift into + SHL(32, R(tempReg2), Imm8(17)); + OR(32, R(tempReg1), R(tempReg2)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +} + +void VertexDecoderJitCache::Jit_TcFloat() { +#ifdef _M_X64 + MOV(64, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(64, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +#else + MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->tcoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff + 4), R(tempReg2)); +#endif +} + +void VertexDecoderJitCache::Jit_TcU8Prescale() { + // TODO: The first five instructions could be done in 1 or 2 in SSE4 + MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->tcoff)); + MOVZX(32, 8, tempReg2, MDisp(srcReg, dec_->tcoff + 1)); + CVTSI2SS(fpScratchReg, R(tempReg1)); + CVTSI2SS(fpScratchReg2, R(tempReg2)); + UNPCKLPS(fpScratchReg, R(fpScratchReg2)); + MULPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + ADDPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); +} + +void VertexDecoderJitCache::Jit_TcU16Prescale() { + PXOR(fpScratchReg2, R(fpScratchReg2)); + MOVD_xmm(fpScratchReg, MDisp(srcReg, dec_->tcoff)); + PUNPCKLWD(fpScratchReg, R(fpScratchReg2)); + CVTDQ2PS(fpScratchReg, R(fpScratchReg)); + MULPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + ADDPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); +} + +void VertexDecoderJitCache::Jit_TcFloatPrescale() { + MOVQ_xmm(fpScratchReg, MDisp(srcReg, dec_->tcoff)); + MULPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + ADDPS(fpScratchReg, R(fpScaleOffsetReg)); + SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); + MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), fpScratchReg); +} + +void VertexDecoderJitCache::Jit_TcU16Through() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +} + +void VertexDecoderJitCache::Jit_TcU16ThroughDouble() { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff)); + MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->tcoff + 2)); + SHL(16, R(tempReg1), Imm8(1)); // 16 to get a wall to shift into + SHL(32, R(tempReg2), Imm8(17)); + OR(32, R(tempReg1), R(tempReg2)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +} + +void VertexDecoderJitCache::Jit_TcFloatThrough() { +#ifdef _M_X64 + MOV(64, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(64, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); +#else + MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->tcoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.uvoff + 4), R(tempReg2)); +#endif +} + +void VertexDecoderJitCache::Jit_Color8888() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->coloff)); + MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg1)); +} + +static const u32 MEMORY_ALIGNED16(nibbles[4]) = { 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, }; + + +void VertexDecoderJitCache::Jit_Color4444() { + // Needs benchmarking. A bit wasteful by only using 1 SSE lane. +#if 0 + // Alternate approach + MOVD_xmm(XMM3, MDisp(srcReg, dec_->coloff)); + MOVAPS(XMM2, R(XMM3)); + MOVAPS(XMM1, M((void *)nibbles)); + PSLLD(XMM2, 4); + PAND(XMM3, R(XMM1)); + PAND(XMM2, R(XMM1)); + PSRLD(XMM2, 4); + PXOR(XMM1, R(XMM1)); + PUNPCKLBW(XMM2, R(XMM1)); + PUNPCKLBW(XMM3, R(XMM1)); + PSLLD(XMM2, 4); + POR(XMM3, R(XMM2)); + MOVAPS(XMM2, R(XMM3)); + PSLLD(XMM2, 4); + POR(XMM3, R(XMM2)); + MOVD_xmm(MDisp(dstReg, dec_->decFmt.c0off), XMM3); + return; +#endif + + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->coloff)); + + // 0000ABGR, copy R and double forwards. + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0x0000000F)); + MOV(32, R(tempReg2), R(tempReg3)); + SHL(32, R(tempReg3), Imm8(4)); + OR(32, R(tempReg2), R(tempReg3)); + + // tempReg1 -> 00ABGR00, then double G backwards. + SHL(32, R(tempReg1), Imm8(8)); + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0x0000F000)); + OR(32, R(tempReg2), R(tempReg3)); + SHR(32, R(tempReg3), Imm8(4)); + OR(32, R(tempReg2), R(tempReg3)); + + // Now do B forwards again (still 00ABGR00.) + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0x000F0000)); + OR(32, R(tempReg2), R(tempReg3)); + SHL(32, R(tempReg3), Imm8(4)); + OR(32, R(tempReg2), R(tempReg3)); + + // tempReg1 -> ABGR0000, then double A backwards. + SHL(32, R(tempReg1), Imm8(8)); + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0xF0000000)); + OR(32, R(tempReg2), R(tempReg3)); + SHR(32, R(tempReg3), Imm8(4)); + OR(32, R(tempReg2), R(tempReg3)); + + MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); +} + +void VertexDecoderJitCache::Jit_Color565() { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->coloff)); + + MOV(32, R(tempReg2), R(tempReg1)); + AND(32, R(tempReg2), Imm32(0x0000001F)); + + // B (we do R and B at the same time, they're both 5.) + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0x0000F800)); + SHL(32, R(tempReg3), Imm8(5)); + OR(32, R(tempReg2), R(tempReg3)); + + // Expand 5 -> 8. At this point we have 00BB00RR. + MOV(32, R(tempReg3), R(tempReg2)); + SHL(32, R(tempReg2), Imm8(3)); + SHR(32, R(tempReg3), Imm8(2)); + OR(32, R(tempReg2), R(tempReg3)); + AND(32, R(tempReg2), Imm32(0x00FF00FF)); + + // Now's as good a time to put in A as any. + OR(32, R(tempReg2), Imm32(0xFF000000)); + + // Last, we need to align, extract, and expand G. + // 3 to align to G, and then 2 to expand to 8. + SHL(32, R(tempReg1), Imm8(3 + 2)); + AND(32, R(tempReg1), Imm32(0x0000FC00)); + MOV(32, R(tempReg3), R(tempReg1)); + // 2 to account for tempReg1 being preshifted, 4 for expansion. + SHR(32, R(tempReg3), Imm8(2 + 4)); + OR(32, R(tempReg1), R(tempReg3)); + AND(32, R(tempReg1), Imm32(0x0000FF00)); + OR(32, R(tempReg2), R(tempReg1)); + + MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); +} + +void VertexDecoderJitCache::Jit_Color5551() { + MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->coloff)); + + MOV(32, R(tempReg2), R(tempReg1)); + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg2), Imm32(0x0000001F)); + AND(32, R(tempReg3), Imm32(0x000003E0)); + SHL(32, R(tempReg3), Imm8(3)); + OR(32, R(tempReg2), R(tempReg3)); + + MOV(32, R(tempReg3), R(tempReg1)); + AND(32, R(tempReg3), Imm32(0x00007C00)); + SHL(32, R(tempReg3), Imm8(6)); + OR(32, R(tempReg2), R(tempReg3)); + + // Expand 5 -> 8. After this is just A. + MOV(32, R(tempReg3), R(tempReg2)); + SHL(32, R(tempReg2), Imm8(3)); + SHR(32, R(tempReg3), Imm8(2)); + // Chop off the bits that were shifted out. + AND(32, R(tempReg3), Imm32(0x00070707)); + OR(32, R(tempReg2), R(tempReg3)); + + // For A, we shift it to a single bit, and then subtract and XOR. + // That's probably the simplest way to expand it... + SHR(32, R(tempReg1), Imm8(15)); + // If it was 0, it's now -1, otherwise it's 0. Easy. + SUB(32, R(tempReg1), Imm8(1)); + XOR(32, R(tempReg1), Imm32(0xFF000000)); + AND(32, R(tempReg1), Imm32(0xFF000000)); + OR(32, R(tempReg2), R(tempReg1)); + + MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); +} + +// Copy 3 bytes and then a zero. Might as well copy four. +void VertexDecoderJitCache::Jit_NormalS8() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); + AND(32, R(tempReg1), Imm32(0x00FFFFFF)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); +} + +// Copy 6 bytes and then 2 zeroes. +void VertexDecoderJitCache::Jit_NormalS16() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); + MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->nrmoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2)); +} + +void VertexDecoderJitCache::Jit_NormalFloat() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->nrmoff + 4)); + MOV(32, R(tempReg3), MDisp(srcReg, dec_->nrmoff + 8)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2)); + MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 8), R(tempReg3)); +} + +// This could be a bit shorter with AVX 3-operand instructions and FMA. +void VertexDecoderJitCache::Jit_WriteMatrixMul(int outOff, bool pos) { + MOVAPS(XMM1, R(XMM3)); + MOVAPS(XMM2, R(XMM3)); + SHUFPS(XMM1, R(XMM1), _MM_SHUFFLE(0, 0, 0, 0)); + SHUFPS(XMM2, R(XMM2), _MM_SHUFFLE(1, 1, 1, 1)); + SHUFPS(XMM3, R(XMM3), _MM_SHUFFLE(2, 2, 2, 2)); + MULPS(XMM1, R(XMM4)); + MULPS(XMM2, R(XMM5)); + MULPS(XMM3, R(XMM6)); + ADDPS(XMM1, R(XMM2)); + ADDPS(XMM1, R(XMM3)); + if (pos) { + ADDPS(XMM1, R(XMM7)); + } + MOVUPS(MDisp(dstReg, outOff), XMM1); +} + +void VertexDecoderJitCache::Jit_NormalS8Skin() { + XORPS(XMM3, R(XMM3)); + MOVD_xmm(XMM1, MDisp(srcReg, dec_->nrmoff)); + PUNPCKLBW(XMM1, R(XMM3)); + PUNPCKLWD(XMM1, R(XMM3)); + PSLLD(XMM1, 24); + PSRAD(XMM1, 24); // Ugly sign extension, can be done faster in SSE4 + CVTDQ2PS(XMM3, R(XMM1)); + MULPS(XMM3, M((void *)&by128)); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +// Copy 6 bytes and then 2 zeroes. +void VertexDecoderJitCache::Jit_NormalS16Skin() { + XORPS(XMM3, R(XMM3)); + MOVQ_xmm(XMM1, MDisp(srcReg, dec_->nrmoff)); + PUNPCKLWD(XMM1, R(XMM3)); + PSLLD(XMM1, 16); + PSRAD(XMM1, 16); // Ugly sign extension, can be done faster in SSE4 + CVTDQ2PS(XMM3, R(XMM1)); + MULPS(XMM3, M((void *)&by32768)); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalFloatSkin() { + MOVUPS(XMM3, MDisp(srcReg, dec_->nrmoff)); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +// Through expands into floats, always. Might want to look at changing this. +void VertexDecoderJitCache::Jit_PosS8Through() { + // TODO: SIMD + for (int i = 0; i < 3; i++) { + MOVSX(32, 8, tempReg1, MDisp(srcReg, dec_->posoff + i)); + CVTSI2SS(fpScratchReg, R(tempReg1)); + MOVSS(MDisp(dstReg, dec_->decFmt.posoff + i * 4), fpScratchReg); + } +} + +// Through expands into floats, always. Might want to look at changing this. +void VertexDecoderJitCache::Jit_PosS16Through() { + XORPS(XMM3, R(XMM3)); + MOVQ_xmm(XMM1, MDisp(srcReg, dec_->posoff)); + PUNPCKLWD(XMM1, R(XMM3)); + PSLLD(XMM1, 16); + PSRAD(XMM1, 16); // Ugly sign extension, can be done faster in SSE4 + CVTDQ2PS(XMM3, R(XMM1)); + MOVUPS(MDisp(dstReg, dec_->decFmt.posoff), XMM3); +} + +// Copy 3 bytes and then a zero. Might as well copy four. +void VertexDecoderJitCache::Jit_PosS8() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); + AND(32, R(tempReg1), Imm32(0x00FFFFFF)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); +} + +// Copy 6 bytes and then 2 zeroes. +void VertexDecoderJitCache::Jit_PosS16() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); + MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->posoff + 4)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2)); +} + +// Just copy 12 bytes. +void VertexDecoderJitCache::Jit_PosFloat() { + MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff)); + MOV(32, R(tempReg2), MDisp(srcReg, dec_->posoff + 4)); + MOV(32, R(tempReg3), MDisp(srcReg, dec_->posoff + 8)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2)); + MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3)); +} + +void VertexDecoderJitCache::Jit_PosS8Skin() { + XORPS(XMM3, R(XMM3)); + MOVD_xmm(XMM1, MDisp(srcReg, dec_->posoff)); + PUNPCKLBW(XMM1, R(XMM3)); + PUNPCKLWD(XMM1, R(XMM3)); + PSLLD(XMM1, 24); + PSRAD(XMM1, 24); // Ugly sign extension, can be done faster in SSE4 + CVTDQ2PS(XMM3, R(XMM1)); + MULPS(XMM3, M((void *)&by128)); + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +void VertexDecoderJitCache::Jit_PosS16Skin() { + XORPS(XMM3, R(XMM3)); + MOVQ_xmm(XMM1, MDisp(srcReg, dec_->posoff)); + PUNPCKLWD(XMM1, R(XMM3)); + PSLLD(XMM1, 16); + PSRAD(XMM1, 16); // Ugly sign extension, can be done faster in SSE4 + CVTDQ2PS(XMM3, R(XMM1)); + MULPS(XMM3, M((void *)&by32768)); + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +// Just copy 12 bytes. +void VertexDecoderJitCache::Jit_PosFloatSkin() { + MOVUPS(XMM3, MDisp(srcReg, dec_->posoff)); + Jit_WriteMatrixMul(dec_->decFmt.posoff, true); +} + +bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { + // See if we find a matching JIT function + for (size_t i = 0; i < ARRAY_SIZE(jitLookup); i++) { + if (dec.steps_[step] == jitLookup[i].func) { + ((*this).*jitLookup[i].jitFunc)(); + return true; + } + } + return false; +} diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 8363c25662..515a11f154 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -110,6 +110,9 @@ void ComputeVertexShaderID(VertexShaderID *id, u32 vertType, int prim, bool useH id->d[1] |= gstate.isLightingEnabled() << 24; id->d[1] |= (vertTypeGetWeightMask(vertType) >> GE_VTYPE_WEIGHT_SHIFT) << 25; id->d[1] |= gstate.areNormalsReversed() << 26; + if (doTextureProjection && gstate.getUVProjMode() == GE_PROJMAP_UV) { + id->d[1] |= ((vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT) << 27; // two bits + } } } @@ -162,7 +165,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf bool hasNormal = (vertType & GE_VTYPE_NRM_MASK) != 0 && useHWTransform; bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear(); bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; - bool flipV = gstate_c.flipTexture; + bool flipV = gstate_c.flipTexture; // This also means that we are texturing from a render target bool flipNormal = gstate.areNormalsReversed(); DoLightComputation doLight[4] = {LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF}; @@ -208,7 +211,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf // Add all the uniforms we'll need to transform properly. } - bool prescale = g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0; + bool prescale = g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN); if (useHWTransform) { // When transforming by hardware, we need a great deal more uniforms... @@ -226,7 +229,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf } #endif } - if (doTexture && (!prescale || gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP || gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX)) { + if (doTexture && (flipV || !prescale || gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP || gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX)) { WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); } for (int i = 0; i < 4; i++) { @@ -537,7 +540,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf switch (gstate.getUVGenMode()) { case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy. case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works. - if (prescale) { + if (prescale && !flipV) { WRITE(p, " v_texcoord = texcoord;\n"); } else { WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); @@ -553,6 +556,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf break; case GE_PROJMAP_UV: // Use unscaled UV as source { + // prescale is false here. static const char *rescaleuv[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f}; const char *factor = rescaleuv[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT]; temp_tc = StringFromFormat("vec4(texcoord.xy %s, 0.0, 1.0)", factor); diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 24a14aa84f..a961adbe4a 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -242,8 +242,16 @@ + + + true + true + true + true + + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index bd55b4335e..a6657c2a69 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -200,6 +200,9 @@ GLES + + GLES + GLES @@ -293,6 +296,8 @@ Common + + diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 7293d3bf8e..3cfff675d4 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -15,22 +15,28 @@ #include "Core/HLE/sceGe.h" GPUCommon::GPUCommon() : - nextListID(0), - currentList(NULL), - isbreak(false), - drawCompleteTicks(0), - busyTicks(0), dumpNextFrame_(false), - dumpThisFrame_(false), - interruptsEnabled_(true), - curTickEst_(0) + dumpThisFrame_(false) { + Reinitialize(); + SetThreadEnabled(g_Config.bSeparateCPUThread); +} + +void GPUCommon::Reinitialize() { + easy_guard guard(listLock); memset(dls, 0, sizeof(dls)); for (int i = 0; i < DisplayListMaxCount; ++i) { dls[i].state = PSP_GE_DL_STATE_NONE; dls[i].waitTicks = 0; } - SetThreadEnabled(g_Config.bSeparateCPUThread); + + nextListID = 0; + currentList = NULL; + isbreak = false; + drawCompleteTicks = 0; + busyTicks = 0; + interruptsEnabled_ = true; + UpdateTickEstimate(0); } void GPUCommon::PopDLQueue() { @@ -725,9 +731,22 @@ void GPUCommon::ExecuteOp(u32 op, u32 diff) { case GE_CMD_CALL: { easy_guard guard(listLock); + // Saint Seiya needs correct support for relative calls. u32 retval = currentList->pc + 4; u32 target = gstate_c.getRelativeAddress(data); + + // Bone matrix optimization - many games will CALL a bone matrix (!). + if (g_Config.bSoftwareSkinning && (Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA) { + // Check for the end + if ((Memory::ReadUnchecked_U32(target + 11 * 4) >> 24) == GE_CMD_BONEMATRIXDATA && + (Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET) { + // Yep, pretty sure this is a bone matrix call. + gstate.FastLoadBoneMatrix(target); + break; + } + } + if (currentList->stackptr == ARRAY_SIZE(currentList->stack)) { ERROR_LOG_REPORT(G3D, "CALL: Stack full!"); } else if (!Memory::IsValidAddress(target)) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 61a725a2a4..769df0c94e 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -19,6 +19,7 @@ class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface public: GPUCommon(); virtual ~GPUCommon() {} + virtual void Reinitialize(); virtual void InterruptStart(int listid); virtual void InterruptEnd(int listid); @@ -72,6 +73,10 @@ public: FreeAlignedMemory(p); } + virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) { + return false; + } + protected: // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 1e3e2e6796..ab1fdd82e4 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -184,6 +184,7 @@ public: // Initialization virtual void InitClear() = 0; + virtual void Reinitialize() = 0; virtual void RunEventsUntil(u64 globalticks) = 0; virtual void FinishEventLoop() = 0; @@ -242,6 +243,9 @@ public: virtual bool FramebufferReallyDirty() = 0; virtual bool BusyDrawing() = 0; + // If any jit is being used inside the GPU. + virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0; + // Debugging virtual void DumpNextFrame() = 0; virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 8f13076493..5289d66a83 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -28,10 +28,18 @@ #include "GPU/Directx9/GPU_DX9.h" #endif #include "Core/CoreParameter.h" +#include "Core/Config.h" #include "Core/System.h" +#include "Core/MemMap.h" +#ifdef _M_SSE +#include +#endif + +// This must be aligned so that the matrices within are aligned. +GPUgstate MEMORY_ALIGNED16(gstate); +// Let's align this one too for good measure. +GPUStateCache MEMORY_ALIGNED16(gstate_c); -GPUgstate gstate; -GPUStateCache gstate_c; GPUInterface *gpu; GPUDebugInterface *gpuDebug; GPUStatistics gpuStats; @@ -53,7 +61,7 @@ bool GPU_Init() { #endif break; case GPU_SOFTWARE: -#if !(defined(__SYMBIAN32__) || defined(_XBOX)) +#ifndef _XBOX SetGPU(new SoftGPU()); #endif break; @@ -73,6 +81,12 @@ void GPU_Shutdown() { gpuDebug = 0; } +void GPU_Reinitialize() { + if (gpu) { + gpu->Reinitialize(); + } +} + void InitGfxState() { memset(&gstate, 0, sizeof(gstate)); memset(&gstate_c, 0, sizeof(gstate_c)); @@ -171,6 +185,34 @@ void GPUgstate::Save(u32_le *ptr) { memcpy(matrices, tgenMatrix, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); } +void GPUgstate::FastLoadBoneMatrix(u32 addr) { + const u32 *src = (const u32 *)Memory::GetPointerUnchecked(addr); + u32 num = boneMatrixNumber; + u32 *dst = (u32 *)(boneMatrix + (num & 0x7F)); + +#ifdef _M_SSE + __m128i row1 = _mm_slli_epi32(_mm_loadu_si128((const __m128i *)src), 8); + __m128i row2 = _mm_slli_epi32(_mm_loadu_si128((const __m128i *)(src + 4)), 8); + __m128i row3 = _mm_slli_epi32(_mm_loadu_si128((const __m128i *)(src + 8)), 8); + if ((num & 0x3) == 0) { + _mm_store_si128((__m128i *)dst, row1); + _mm_store_si128((__m128i *)(dst + 4), row2); + _mm_store_si128((__m128i *)(dst + 8), row3); + } else { + _mm_storeu_si128((__m128i *)dst, row1); + _mm_storeu_si128((__m128i *)(dst + 4), row2); + _mm_storeu_si128((__m128i *)(dst + 8), row3); + } +#else + for (int i = 0; i < 12; i++) { + dst[i] = src[i] << 8; + } +#endif + + num += 12; + gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x7F); +} + void GPUgstate::Restore(u32_le *ptr) { // Not sure what the first 10 values are, exactly, but these seem right. gstate_c.vertexAddr = ptr[5]; @@ -200,3 +242,10 @@ void GPUgstate::Restore(u32_le *ptr) { memcpy(projMatrix, matrices, sizeof(projMatrix)); matrices += sizeof(projMatrix); memcpy(tgenMatrix, matrices, sizeof(tgenMatrix)); matrices += sizeof(tgenMatrix); } + +bool vertTypeIsSkinningEnabled(u32 vertType) { + if (g_Config.bSoftwareSkinning && ((vertType & GE_VTYPE_MORPHCOUNT_MASK) == 0)) + return false; + else + return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); +} diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 2a78e02f5a..3473e864f7 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -18,6 +18,7 @@ #pragma once #include + #include "../Globals.h" #include "ge_constants.h" #include "Common/Common.h" @@ -212,6 +213,7 @@ struct GPUgstate float tgenMatrix[12]; float boneMatrix[12 * 8]; // Eight bone matrices. + // Framebuffer u32 getFrameBufRawAddress() const { return (fbptr & 0xFFFFFF) | ((fbwidth & 0xFF0000) << 8); } // 0x44000000 is uncached VRAM. u32 getFrameBufAddress() const { return 0x44000000 | getFrameBufRawAddress(); } @@ -228,7 +230,8 @@ struct GPUgstate // Cull bool isCullEnabled() const { return cullfaceEnable & 1; } int getCullMode() const { return cullmode & 1; } - bool isClearModeDepthWriteEnabled() const { return (clearmode&0x400) != 0; } + + // Color Mask bool isClearModeColorMask() const { return (clearmode&0x100) != 0; } bool isClearModeAlphaMask() const { return (clearmode&0x200) != 0; } bool isClearModeDepthMask() const { return (clearmode&0x400) != 0; } @@ -236,9 +239,9 @@ struct GPUgstate // Blend GEBlendSrcFactor getBlendFuncA() const { return (GEBlendSrcFactor)(blend & 0xF); } + GEBlendDstFactor getBlendFuncB() const { return (GEBlendDstFactor)((blend >> 4) & 0xF); } u32 getFixA() const { return blendfixa & 0xFFFFFF; } u32 getFixB() const { return blendfixb & 0xFFFFFF; } - GEBlendDstFactor getBlendFuncB() const { return (GEBlendDstFactor)((blend >> 4) & 0xF); } GEBlendMode getBlendEq() const { return static_cast((blend >> 8) & 0x7); } bool isAlphaBlendEnabled() const { return alphaBlendEnable & 1; } @@ -298,6 +301,7 @@ struct GPUgstate int getTextureEnvColB() const { return (texenvcolor>>16)&0xFF; } u32 getClutAddress() const { return (clutaddr & 0x00FFFFFF) | ((clutaddrupper << 8) & 0x0F000000); } int getClutLoadBytes() const { return (loadclut & 0x3F) * 32; } + int getClutLoadBlocks() const { return (loadclut & 0x3F); } GEPaletteFormat getClutPaletteFormat() { return static_cast(clutformat & 3); } int getClutIndexShift() const { return (clutformat >> 2) & 0x1F; } int getClutIndexMask() const { return (clutformat >> 8) & 0xFF; } @@ -305,6 +309,7 @@ struct GPUgstate int transformClutIndex(int index) const { return ((index >> getClutIndexShift()) & getClutIndexMask()) | getClutIndexStartPos(); } bool isClutIndexSimple() const { return (clutformat & ~3) == 0xC500FF00; } // Meaning, no special mask, shift, or start pos. bool isTextureSwizzled() const { return texmode & 1; } + bool isClutSharedForMipmaps() const { return (texmode & 0x100) == 0; } // Lighting bool isLightingEnabled() const { return lightingEnable & 1; } @@ -382,18 +387,23 @@ struct GPUgstate // Transfers u32 getTransferSrcAddress() const { return (transfersrc & 0xFFFFF0) | ((transfersrcw & 0xFF0000) << 8); } - u32 getTransferSrcStride() const { return transfersrcw & 0x3F8; } + // Bits 0xf800 are ignored, > 0x400 is treated as 0. + u32 getTransferSrcStride() const { int stride = transfersrcw & 0x7F8; return stride > 0x400 ? 0 : stride; } int getTransferSrcX() const { return (transfersrcpos >> 0) & 0x3FF; } int getTransferSrcY() const { return (transfersrcpos >> 10) & 0x3FF; } u32 getTransferDstAddress() const { return (transferdst & 0xFFFFF0) | ((transferdstw & 0xFF0000) << 8); } - u32 getTransferDstStride() const { return transferdstw & 0x3F8; } + // Bits 0xf800 are ignored, > 0x400 is treated as 0. + u32 getTransferDstStride() const { int stride = transferdstw & 0x7F8; return stride > 0x400 ? 0 : stride; } int getTransferDstX() const { return (transferdstpos >> 0) & 0x3FF; } int getTransferDstY() const { return (transferdstpos >> 10) & 0x3FF; } int getTransferWidth() const { return ((transfersize >> 0) & 0x3FF) + 1; } int getTransferHeight() const { return ((transfersize >> 10) & 0x3FF) + 1; } int getTransferBpp() const { return (transferstart & 1) ? 4 : 2; } -// Real data in the context ends here + + void FastLoadBoneMatrix(u32 addr); + + // Real data in the context ends here void Save(u32_le *ptr); void Restore(u32_le *ptr); @@ -405,7 +415,8 @@ enum SkipDrawReasonFlags { SKIPDRAW_BAD_FB_TEXTURE = 4, }; -inline bool vertTypeIsSkinningEnabled(u32 vertType) { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); } +bool vertTypeIsSkinningEnabled(u32 vertType); + inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); } inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; } inline int vertTypeGetTexCoordMask(u32 vertType) { return vertType & GE_VTYPE_TC_MASK; } @@ -514,6 +525,7 @@ struct GPUStatistics { bool GPU_Init(); void GPU_Shutdown(); +void GPU_Reinitialize(); void InitGfxState(); void ShutdownGfxState(); diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index c104a71fa0..cafb50b6f8 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -47,18 +47,24 @@ void GeDescribeVertexType(u32 op, char *buffer, int len) { "u16", "float", }; + static const char *typeNamesS[] = { + NULL, + "s8", + "s16", + "float", + }; char *w = buffer, *end = buffer + len; if (through) w += snprintf(w, end - w, "through, "); if (typeNames[tc]) - w += snprintf(w, end - w, "%s UVs, ", typeNames[tc]); + w += snprintf(w, end - w, "%s texcoords, ", typeNames[tc]); if (colorNames[col]) w += snprintf(w, end - w, "%s colors, ", colorNames[col]); if (typeNames[nrm]) - w += snprintf(w, end - w, "%s normals, ", typeNames[nrm]); + w += snprintf(w, end - w, "%s normals, ", typeNamesS[nrm]); if (typeNames[pos]) - w += snprintf(w, end - w, "%s coords, ", typeNames[pos]); + w += snprintf(w, end - w, "%s positions, ", typeNamesS[pos]); if (typeNames[weight]) w += snprintf(w, end - w, "%s weights (%d), ", typeNames[weight], weightCount); else if (weightCount > 0) diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 5838c3e921..49311a7433 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -40,6 +40,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec2() {} Vec2(const T a[2]) : x(a[0]), y(a[1]) {} @@ -155,12 +156,6 @@ public: Vec2 ts() const { return Vec2(y, x); } }; -template -Vec2 operator * (const V& f, const Vec2& vec) -{ - return Vec2(f*vec.x,f*vec.y); -} - typedef Vec2 Vec2f; template @@ -173,6 +168,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec3() {} Vec3(const T a[3]) : x(a[0]), y(a[1]), z(a[2]) {} @@ -321,12 +317,6 @@ public: #undef _DEFINE_SWIZZLER2 }; -template -Vec3 operator * (const V& f, const Vec3& vec) -{ - return Vec3(f*vec.x,f*vec.y,f*vec.z); -} - typedef Vec3 Vec3f; template @@ -339,6 +329,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec4() {} Vec4(const T a[4]) : x(a[0]), y(a[1]), z(a[2]), w(a[3]) {} @@ -494,12 +485,6 @@ public: #undef _DEFINE_SWIZZLER3 }; -template -Vec4 operator * (const V& f, const Vec4& vec) -{ - return Vec4(f*vec.x,f*vec.y,f*vec.z,f*vec.w); -} - typedef Vec4 Vec4f; @@ -530,7 +515,7 @@ public: } template - Vec3 operator * (const Vec3& vec) + Vec3 operator * (const Vec3& vec) const { Vec3 ret; ret.x = values[0]*vec.x + values[3]*vec.y + values[6]*vec.z; @@ -539,7 +524,7 @@ public: return ret; } - Mat3x3 Inverse() + Mat3x3 Inverse() const { float a = values[0]; float b = values[1]; @@ -555,7 +540,7 @@ public: b*f-c*e, c*d-a*f, a*e-b*d) / Det(); } - BaseType Det() + BaseType Det() const { return values[0]*values[4]*values[8] + values[3]*values[7]*values[2] + values[6]*values[1]*values[5] - values[2]*values[4]*values[6] - @@ -588,7 +573,7 @@ public: } template - Vec4 operator * (const Vec4& vec) + Vec4 operator * (const Vec4& vec) const { Vec4 ret; ret.x = values[0]*vec.x + values[4]*vec.y + values[8]*vec.z + values[12]*vec.w; @@ -612,12 +597,21 @@ inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) { - vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[9]; - vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[10]; - vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[11]; + vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12]; + vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13]; + vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14]; vecOut[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + m[15]; } +inline void Vec4ByMatrix44(float vecOut[4], const float v[4], const float m[16]) +{ + vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12]; + vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13]; + vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14]; + vecOut[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15]; +} + + inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) { vecOut[0] = v[0] * m[0] + v[1] * m[3] + v[2] * m[6]; @@ -625,6 +619,14 @@ inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12] vecOut[2] = v[0] * m[2] + v[1] * m[5] + v[2] * m[8]; } +inline void Matrix4ByMatrix4(float out[16], const float a[16], const float b[16]) { + Vec4ByMatrix44(out, a, b); + Vec4ByMatrix44(out + 4, a + 4, b); + Vec4ByMatrix44(out + 8, a + 8, b); + Vec4ByMatrix44(out + 12, a + 12, b); +} + + inline float Vec3Dot(const float v1[3], const float v2[3]) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index f080503c11..050588cdd8 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -46,6 +46,10 @@ public: fullInfo = "NULL"; } + virtual bool FramebufferReallyDirty() { + return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME); + } + protected: virtual void FastRunLoop(DisplayList &list); }; diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index 4aecbba63c..11cd6ccae4 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -99,7 +99,7 @@ static inline int CalcClipMask(const ClipCoords& v) #define CLIP_LINE(PLANE_BIT, A, B, C, D) \ { \ -if (mask & PLANE_BIT) { \ + if (mask & PLANE_BIT) { \ float dp0 = CLIP_DOTPROD(0, A, B, C, D ); \ float dp1 = CLIP_DOTPROD(1, A, B, C, D ); \ int i = 0; \ @@ -158,6 +158,7 @@ void ProcessQuad(const VertexData& v0, const VertexData& v1) bottomright = &buf[i]; } + // Four triangles to do backfaces as well. Two of them will get backface culled. ProcessTriangle(*topleft, *topright, *bottomright); ProcessTriangle(*bottomright, *topright, *topleft); ProcessTriangle(*bottomright, *bottomleft, *topleft); @@ -197,6 +198,7 @@ void ProcessQuad(const VertexData& v0, const VertexData& v1) bottomright = &buf[i]; } + // Four triangles to do backfaces as well. Two of them will get backface culled. Rasterizer::DrawTriangle(*topleft, *topright, *bottomright); Rasterizer::DrawTriangle(*bottomright, *topright, *topleft); Rasterizer::DrawTriangle(*bottomright, *bottomleft, *topleft); @@ -204,6 +206,23 @@ void ProcessQuad(const VertexData& v0, const VertexData& v1) } } +void ProcessPoint(VertexData& v0) +{ + // Points need no clipping. + Rasterizer::DrawPoint(v0); +} + +void ProcessLine(VertexData& v0, VertexData& v1) +{ + if (gstate.isModeThrough()) { + // Actually, should clip this one too so we don't need to do bounds checks in the rasterizer. + Rasterizer::DrawLine(v0, v1); + return; + } + + // TODO: 3D lines +} + void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2) { if (gstate.isModeThrough()) { @@ -238,7 +257,7 @@ void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2) if (mask & CLIP_NEG_Z_BIT) return; - for(int i = 0; i < 3; i += 3) { + for (int i = 0; i < 3; i += 3) { int vlist[2][2*6+1]; int *inlist = vlist[0], *outlist = vlist[1]; int n = 3; @@ -276,7 +295,7 @@ void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2) return; } - for(int i = 0; i+3 <= numIndices; i+=3) + for (int i = 0; i+3 <= numIndices; i+=3) { if(indices[i] != SKIP_FLAG) { diff --git a/GPU/Software/Clipper.h b/GPU/Software/Clipper.h index ebf7983f2d..7c1881a50b 100644 --- a/GPU/Software/Clipper.h +++ b/GPU/Software/Clipper.h @@ -21,6 +21,8 @@ namespace Clipper { +void ProcessPoint(VertexData& v0); +void ProcessLine(VertexData& v0, VertexData& v1); void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2); void ProcessQuad(const VertexData& v0, const VertexData& v1); diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 314e983234..40260d40ca 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -15,6 +15,9 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "base/basictypes.h" + +#include "Common/ThreadPools.h" #include "Core/MemMap.h" #include "Core/Reporting.h" #include "GPU/GPUState.h" @@ -49,20 +52,21 @@ static inline int orient2dIncY(int dX01) return -dX01; } -static inline int GetPixelDataOffset(unsigned int texel_size_bits, unsigned int row_pitch_bits, unsigned int u, unsigned int v) +template +static inline int GetPixelDataOffset(unsigned int row_pitch_bits, unsigned int u, unsigned int v) { if (!gstate.isTextureSwizzled()) - return v * row_pitch_bits *texel_size_bits/8 / 8 + u * texel_size_bits / 8; + return (v * (row_pitch_bits * texel_size_bits >> 6)) + (u * texel_size_bits >> 3); - int tile_size_bits = 32; - int tiles_in_block_horizontal = 4; - int tiles_in_block_vertical = 8; + const int tile_size_bits = 32; + const int tiles_in_block_horizontal = 4; + const int tiles_in_block_vertical = 8; int texels_per_tile = tile_size_bits / texel_size_bits; int tile_u = u / texels_per_tile; int tile_idx = (v % tiles_in_block_vertical) * (tiles_in_block_horizontal) + // TODO: not sure if the *texel_size_bits/8 factor is correct - (v / tiles_in_block_vertical) * ((row_pitch_bits*texel_size_bits/8/tile_size_bits)*tiles_in_block_vertical) + + (v / tiles_in_block_vertical) * ((row_pitch_bits*texel_size_bits/(8*tile_size_bits))*tiles_in_block_vertical) + (tile_u % tiles_in_block_horizontal) + (tile_u / tiles_in_block_horizontal) * (tiles_in_block_horizontal*tiles_in_block_vertical); @@ -72,10 +76,9 @@ static inline int GetPixelDataOffset(unsigned int texel_size_bits, unsigned int static inline u32 LookupColor(unsigned int index, unsigned int level) { - const bool mipmapShareClut = (gstate.texmode & 0x100) == 0; + const bool mipmapShareClut = gstate.isClutSharedForMipmaps(); const int clutSharingOffset = mipmapShareClut ? 0 : level * 16; - // TODO: No idea if these bswaps are correct switch (gstate.getClutPaletteFormat()) { case GE_TFMT_5650: return DecodeRGB565(reinterpret_cast(clut)[index + clutSharingOffset]); @@ -95,52 +98,91 @@ static inline u32 LookupColor(unsigned int index, unsigned int level) } } -static inline void GetTexelCoordinates(int level, float s, float t, unsigned int& u, unsigned int& v) +static inline void GetTexelCoordinates(int level, float s, float t, int& out_u, int& out_v) { - s *= getFloat24(gstate.texscaleu); - t *= getFloat24(gstate.texscalev); - - s += getFloat24(gstate.texoffsetu); - t += getFloat24(gstate.texoffsetv); - - // TODO: Is this really only necessary for UV mapping? - if (gstate.isTexCoordClampedS()) { - if (s > 1.0) s = 1.0; - if (s < 0) s = 0; - } else { - // Subtracting floor works for negative and positive to discard the non-fractional part. - s -= floor(s); - } - if (gstate.isTexCoordClampedT()) { - if (t > 1.0) t = 1.0; - if (t < 0.0) t = 0.0; - } else { - // Subtracting floor works for negative and positive to discard the non-fractional part. - t -= floor(t); - } - int width = 1 << (gstate.texsize[level] & 0xf); int height = 1 << ((gstate.texsize[level]>>8) & 0xf); - // TODO: These should really be multiplied by 256 to get fixed point coordinates - // so we can do texture filtering later. + int u = (int)(s * width); + int v = (int)(t * height); - u = (unsigned int)(s * width); // TODO: width-1 instead? - v = (unsigned int)(t * height); // TODO: width-1 instead? + if (gstate.isTexCoordClampedS()) { + if (u >= width - 1) + u = width - 1; + else if (u < 0) + u = 0; + } else { + u &= width - 1; + } + if (gstate.isTexCoordClampedT()) { + if (v >= height - 1) + v = height - 1; + else if (v < 0) + v = 0; + } else { + v &= height - 1; + } + + out_u = u; + out_v = v; } -static inline void GetTexelCoordinatesThrough(int level, float s, float t, unsigned int& u, unsigned int& v) +static inline void GetTexelCoordinatesQuad(int level, float in_s, float in_t, int u[4], int v[4], int &frac_u, int &frac_v) +{ + // 8 bits of fractional UV + int width = 1 << (gstate.texsize[level] & 0xf); + int height = 1 << ((gstate.texsize[level]>>8) & 0xf); + + int base_u = in_s * width * 256; + int base_v = in_t * height * 256; + + frac_u = (int)(base_u) & 0xff; + frac_v = (int)(base_v) & 0xff; + + base_u >>= 8; + base_v >>= 8; + + // Need to generate and individually wrap/clamp the four sample coordinates. Ugh. + + if (gstate.isTexCoordClampedS()) { + for (int i = 0; i < 4; i++) { + int temp_u = base_u + (i & 1); + if (temp_u > width - 1) + temp_u = width - 1; + else if (temp_u < 0) + temp_u = 0; + u[i] = temp_u; + } + } else { + for (int i = 0; i < 4; i++) { + u[i] = (base_u + (i & 1)) & (width - 1); + } + } + if (gstate.isTexCoordClampedT()) { + for (int i = 0; i < 4; i++) { + int temp_v = base_v + ((i & 2) >> 1); + if (temp_v > height - 1) + temp_v = height - 1; + else if (temp_v < 0) + temp_v = 0; + v[i] = temp_v; + } + } else { + for (int i = 0; i < 4; i++) { + v[i] = (base_v + ((i & 2) >> 1)) & (height - 1); + } + } +} + +static inline void GetTexelCoordinatesThrough(int level, int s, int t, int& u, int& v) { // Not actually sure which clamp/wrap modes should be applied. Let's just wrap for now. int width = 1 << (gstate.texsize[level] & 0xf); int height = 1 << ((gstate.texsize[level]>>8) & 0xf); - // TODO: These should really be multiplied by 256 to get fixed point coordinates - // so we can do texture filtering later. - // Wrap! - u = (unsigned int)(s) & (width - 1); - v = (unsigned int)(t) & (height - 1); + u = ((unsigned int)(s) & (width - 1)); + v = ((unsigned int)(t) & (height - 1)); } static inline void GetTextureCoordinates(const VertexData& v0, const VertexData& v1, const VertexData& v2, int w0, int w1, int w2, float& s, float& t) @@ -165,9 +207,9 @@ static inline void GetTextureCoordinates(const VertexData& v0, const VertexData& // projection mapping, TODO: Move this code to TransformUnit! Vec3 source; if (gstate.getUVProjMode() == GE_PROJMAP_POSITION) { - source = ((v0.modelpos * w0 + v1.modelpos * w1 + v2.modelpos * w2) / (w0+w1+w2)); + source = ((v0.modelpos * w0 + v1.modelpos * w1 + v2.modelpos * w2) / (w0+w1+w2)); } else { - ERROR_LOG_REPORT(G3D, "Software: Unsupported UV projection mode %x", gstate.getUVProjMode()); + ERROR_LOG_REPORT(G3D, "Software: Unsupported UV projection mode %x", gstate.getUVProjMode()); } Mat3x3 tgen(gstate.tgenMatrix); @@ -182,72 +224,73 @@ static inline void GetTextureCoordinates(const VertexData& v0, const VertexData& } } -static inline u32 SampleNearest(int level, unsigned int u, unsigned int v, u8 *srcptr, int texbufwidthbits) +static inline u32 SampleNearest(int level, unsigned int u, unsigned int v, const u8 *srcptr, int texbufwidthbits) { if (!srcptr) return 0; + GETextureFormat texfmt = gstate.getTextureFormat(); // TODO: Should probably check if textures are aligned properly... switch (texfmt) { case GE_TFMT_4444: - srcptr += GetPixelDataOffset(16, texbufwidthbits, u, v); - return DecodeRGBA4444(*(u16*)srcptr); + srcptr += GetPixelDataOffset<16>(texbufwidthbits, u, v); + return DecodeRGBA4444(*(const u16*)srcptr); case GE_TFMT_5551: - srcptr += GetPixelDataOffset(16, texbufwidthbits, u, v); - return DecodeRGBA5551(*(u16*)srcptr); + srcptr += GetPixelDataOffset<16>(texbufwidthbits, u, v); + return DecodeRGBA5551(*(const u16*)srcptr); case GE_TFMT_5650: - srcptr += GetPixelDataOffset(16, texbufwidthbits, u, v); - return DecodeRGB565(*(u16*)srcptr); + srcptr += GetPixelDataOffset<16>(texbufwidthbits, u, v); + return DecodeRGB565(*(const u16*)srcptr); case GE_TFMT_8888: - srcptr += GetPixelDataOffset(32, texbufwidthbits, u, v); - return DecodeRGBA8888(*(u32*)srcptr); + srcptr += GetPixelDataOffset<32>(texbufwidthbits, u, v); + return DecodeRGBA8888(*(const u32 *)srcptr); case GE_TFMT_CLUT32: { - srcptr += GetPixelDataOffset(32, texbufwidthbits, u, v); + srcptr += GetPixelDataOffset<32>(texbufwidthbits, u, v); u32 val = srcptr[0] + (srcptr[1] << 8) + (srcptr[2] << 16) + (srcptr[3] << 24); return LookupColor(gstate.transformClutIndex(val), level); } case GE_TFMT_CLUT16: { - srcptr += GetPixelDataOffset(16, texbufwidthbits, u, v); + srcptr += GetPixelDataOffset<16>(texbufwidthbits, u, v); u16 val = srcptr[0] + (srcptr[1] << 8); return LookupColor(gstate.transformClutIndex(val), level); } case GE_TFMT_CLUT8: { - srcptr += GetPixelDataOffset(8, texbufwidthbits, u, v); + srcptr += GetPixelDataOffset<8>(texbufwidthbits, u, v); u8 val = *srcptr; return LookupColor(gstate.transformClutIndex(val), level); } case GE_TFMT_CLUT4: { - srcptr += GetPixelDataOffset(4, texbufwidthbits, u, v); + srcptr += GetPixelDataOffset<4>(texbufwidthbits, u, v); u8 val = (u & 1) ? (srcptr[0] >> 4) : (srcptr[0] & 0xF); return LookupColor(gstate.transformClutIndex(val), level); } case GE_TFMT_DXT1: { - DXT1Block *block = (DXT1Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); + const DXT1Block *block = (const DXT1Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); u32 data[4 * 4]; DecodeDXT1Block(data, block, 4); return DecodeRGBA8888(data[4 * (v % 4) + (u % 4)]); } case GE_TFMT_DXT3: { - DXT3Block *block = (DXT3Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); + const DXT3Block *block = (const DXT3Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); u32 data[4 * 4]; DecodeDXT3Block(data, block, 4); return DecodeRGBA8888(data[4 * (v % 4) + (u % 4)]); } case GE_TFMT_DXT5: { - DXT5Block *block = (DXT5Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); + const DXT5Block *block = (const DXT5Block *)srcptr + (v / 4) * (texbufwidthbits / 8 / 4) + (u / 4); u32 data[4 * 4]; DecodeDXT5Block(data, block, 4); return DecodeRGBA8888(data[4 * (v % 4) + (u % 4)]); @@ -353,9 +396,6 @@ static inline bool DepthTestPassed(int x, int y, u16 z) { u16 reference_z = GetPixelDepth(x, y); - if (gstate.isModeClear()) - return true; - switch (gstate.getDepthTestFunction()) { case GE_COMP_NEVER: return false; @@ -572,7 +612,7 @@ static inline Vec4 GetTextureFunctionOutput(const Vec3& prim_color_rgb { int t = (rgba) ? texcolor.a() : 255; int invt = (rgba) ? 255 - t : 0; - out_rgb = (invt * prim_color_rgb + t * texcolor.rgb()) / 255; + out_rgb = (prim_color_rgb * invt + texcolor.rgb() * t) / 255; out_a = prim_color_a; break; } @@ -788,42 +828,42 @@ static inline Vec3 AlphaBlendingResult(const Vec3& source_rgb, int sou } } -// Draws triangle, vertices specified in counter-clockwise direction -void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2) +template +void DrawTriangleSlice( + const VertexData& v0, const VertexData& v1, const VertexData& v2, + int minX, int minY, int maxX, int maxY, + int y1, int y2) { Vec2 d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y); Vec2 d02((int)v0.screenpos.x - (int)v2.screenpos.x, (int)v0.screenpos.y - (int)v2.screenpos.y); Vec2 d12((int)v1.screenpos.x - (int)v2.screenpos.x, (int)v1.screenpos.y - (int)v2.screenpos.y); - - // Drop primitives which are not in CCW order by checking the cross product - if (d01.x * d02.y - d01.y * d02.x < 0) - return; - - int minX = std::min(std::min(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) / 16 * 16; - int minY = std::min(std::min(v0.screenpos.y, v1.screenpos.y), v2.screenpos.y) / 16 * 16; - int maxX = std::max(std::max(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) / 16 * 16; - int maxY = std::max(std::max(v0.screenpos.y, v1.screenpos.y), v2.screenpos.y) / 16 * 16; - - DrawingCoords scissorTL(gstate.getScissorX1(), gstate.getScissorY1(), 0); - DrawingCoords scissorBR(gstate.getScissorX2(), gstate.getScissorY2(), 0); - minX = std::max(minX, (int)TransformUnit::DrawingToScreen(scissorTL).x); - maxX = std::min(maxX, (int)TransformUnit::DrawingToScreen(scissorBR).x); - minY = std::max(minY, (int)TransformUnit::DrawingToScreen(scissorTL).y); - maxY = std::min(maxY, (int)TransformUnit::DrawingToScreen(scissorBR).y); + float texScaleU = getFloat24(gstate.texscaleu); + float texScaleV = getFloat24(gstate.texscalev); + float texOffsetU = getFloat24(gstate.texoffsetu); + float texOffsetV = getFloat24(gstate.texoffsetv); int bias0 = IsRightSideOrFlatBottomLine(v0.screenpos.xy(), v1.screenpos.xy(), v2.screenpos.xy()) ? -1 : 0; int bias1 = IsRightSideOrFlatBottomLine(v1.screenpos.xy(), v2.screenpos.xy(), v0.screenpos.xy()) ? -1 : 0; int bias2 = IsRightSideOrFlatBottomLine(v2.screenpos.xy(), v0.screenpos.xy(), v1.screenpos.xy()) ? -1 : 0; - int texlevel = 0; - int texbufwidthbits = 0; - u8 *texptr = NULL; - if (gstate.isTextureMapEnabled() && !gstate.isModeClear()) { + int texbufwidthbits[8] = {0}; + + int maxTexLevel = (gstate.texmode >> 16) & 7; + u8 *texptr[8] = {NULL}; + + if ((gstate.texfilter & 4) == 0) { + // No mipmapping enabled + maxTexLevel = 0; + } + + if (gstate.isTextureMapEnabled() && !clearMode) { // TODO: Always using level 0. GETextureFormat texfmt = gstate.getTextureFormat(); - u32 texaddr = gstate.getTextureAddress(texlevel); - texbufwidthbits = GetTextureBufw(texlevel, texaddr, texfmt) * 8; - texptr = Memory::GetPointer(texaddr); + for (int i = 0; i <= maxTexLevel; i++) { + u32 texaddr = gstate.getTextureAddress(i); + texbufwidthbits[i] = GetTextureBufw(i, texaddr, texfmt) * 8; + texptr[i] = Memory::GetPointer(texaddr); + } } ScreenCoords pprime(minX, minY, 0); @@ -831,22 +871,30 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& int w1_base = orient2d(v2.screenpos, v0.screenpos, pprime); int w2_base = orient2d(v0.screenpos, v1.screenpos, pprime); - for (pprime.y = minY; pprime.y <= maxY; pprime.y +=16, + w0_base += orient2dIncY(d12.x) * 16 * y1; + w1_base += orient2dIncY(-d02.x) * 16 * y1; + w2_base += orient2dIncY(d01.x) * 16 * y1; + + for (pprime.y = minY + y1 * 16; pprime.y < minY + y2 * 16; pprime.y += 16, w0_base += orient2dIncY(d12.x)*16, w1_base += orient2dIncY(-d02.x)*16, w2_base += orient2dIncY(d01.x)*16) { int w0 = w0_base; int w1 = w1_base; int w2 = w2_base; - for (pprime.x = minX; pprime.x <= maxX; pprime.x +=16, - w0 += orient2dIncX(d12.y)*16, - w1 += orient2dIncX(-d02.y)*16, - w2 += orient2dIncX(d01.y)*16) { - DrawingCoords p = TransformUnit::ScreenToDrawing(pprime); + + pprime.x = minX; + DrawingCoords p = TransformUnit::ScreenToDrawing(pprime); + + for (; pprime.x <= maxX; pprime.x +=16, + w0 += orient2dIncX(d12.y)*16, + w1 += orient2dIncX(-d02.y)*16, + w2 += orient2dIncX(d01.y)*16, + p.x = (p.x + 1) & 0x3FF) { // If p is on or inside all edges, render pixel // TODO: Should we render if the pixel is both on the left and the right side? (i.e. degenerated triangle) - if (w0 + bias0 >=0 && w1 + bias1 >= 0 && w2 + bias2 >= 0) { + if (w0 + bias0 >= 0 && w1 + bias1 >= 0 && w2 + bias2 >= 0) { // TODO: Check if this check is still necessary if (w0 == 0 && w1 == 0 && w2 == 0) continue; @@ -856,7 +904,7 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& Vec3 prim_color_rgb(0, 0, 0); int prim_color_a = 0; Vec3 sec_color(0, 0, 0); - if (gstate.getShadeMode() == GE_SHADE_GOURAUD) { + if (gstate.getShadeMode() == GE_SHADE_GOURAUD && !clearMode) { // NOTE: When not casting color0 and color1 to float vectors, this code suffers from severe overflow issues. // Not sure if that should be regarded as a bug or if casting to float is a valid fix. // TODO: Is that the correct way to interpolate? @@ -873,32 +921,88 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& sec_color = v2.color1; } - if (gstate.isTextureMapEnabled() && !gstate.isModeClear()) { - unsigned int u = 0, v = 0; + if (gstate.isTextureMapEnabled() && !clearMode) { + int u[4] = {0}, v[4] = {0}; // 1.23.8 fixed point + int frac_u, frac_v; + + int texlevel = 0; + + int magFilt = (gstate.texfilter>>8) & 1; + + bool bilinear = magFilt != 0; + // bilinear = false; + if (gstate.isModeThrough()) { // TODO: Is it really this simple? float s = ((v0.texturecoords.s() * w0 + v1.texturecoords.s() * w1 + v2.texturecoords.s() * w2) * wsum); float t = ((v0.texturecoords.t() * w0 + v1.texturecoords.t() * w1 + v2.texturecoords.t() * w2) * wsum); - GetTexelCoordinatesThrough(0, s, t, u, v); + + int u_texel = s * 256; + int v_texel = t * 256; + frac_u = u_texel & 0xff; + frac_v = v_texel & 0xff; + u_texel >>= 8; + v_texel >>= 8; + + // we need to compute UV for a quad of pixels together in order to get the mipmap deltas :( + // texlevel = x + + if (texlevel > maxTexLevel) + texlevel = maxTexLevel; + + GetTexelCoordinatesThrough(texlevel, u_texel, v_texel, u[0], v[0]); + if (bilinear) { + GetTexelCoordinatesThrough(texlevel, u_texel + 1, v_texel, u[1], v[1]); + GetTexelCoordinatesThrough(texlevel, u_texel, v_texel + 1, u[2], v[2]); + GetTexelCoordinatesThrough(texlevel, u_texel + 1, v_texel + 1, u[3], v[3]); + } } else { float s = 0, t = 0; GetTextureCoordinates(v0, v1, v2, w0, w1, w2, s, t); - GetTexelCoordinates(0, s, t, u, v); + s = s * texScaleU + texOffsetU; + t = t * texScaleV + texOffsetV; + + // we need to compute UV for a quad of pixels together in order to get the mipmap deltas :( + // texlevel = x + + if (texlevel > maxTexLevel) + texlevel = maxTexLevel; + + if (bilinear) { + GetTexelCoordinatesQuad(texlevel, s, t, u, v, frac_u, frac_v); + } else { + GetTexelCoordinates(texlevel, s, t, u[0], v[0]); + } } - Vec4 texcolor = Vec4::FromRGBA(SampleNearest(texlevel, u, v, texptr, texbufwidthbits)); + Vec4 texcolor; + int bufwbits = texbufwidthbits[texlevel]; + const u8 *tptr = texptr[texlevel]; + if (!bilinear) { + // Nearest filtering only. Round texcoords or just chop bits? + texcolor = Vec4::FromRGBA(SampleNearest(texlevel, u[0], v[0], tptr, bufwbits)); + } else { + Vec4 texcolor_tl = Vec4::FromRGBA(SampleNearest(texlevel, u[0], v[0], tptr, bufwbits)); + Vec4 texcolor_tr = Vec4::FromRGBA(SampleNearest(texlevel, u[1], v[1], tptr, bufwbits)); + Vec4 texcolor_bl = Vec4::FromRGBA(SampleNearest(texlevel, u[2], v[2], tptr, bufwbits)); + Vec4 texcolor_br = Vec4::FromRGBA(SampleNearest(texlevel, u[3], v[3], tptr, bufwbits)); + Vec4 t = texcolor_tl * (0xff - frac_u) + texcolor_tr * frac_u; + Vec4 b = texcolor_bl * (0xff - frac_u) + texcolor_br * frac_u; + texcolor = (t * (0xff - frac_v) + b * frac_v) / (256 * 256); + } Vec4 out = GetTextureFunctionOutput(prim_color_rgb, prim_color_a, texcolor); prim_color_rgb = out.rgb(); prim_color_a = out.a(); } - if (gstate.isColorDoublingEnabled()) { + if (gstate.isColorDoublingEnabled() && !clearMode) { // TODO: Do we need to clamp here? prim_color_rgb *= 2; sec_color *= 2; } - prim_color_rgb += sec_color; + if (!clearMode) + prim_color_rgb += sec_color; // TODO: Fogging @@ -907,22 +1011,24 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& u16 z = (u16)(u32)(((float)v0.screenpos.z * w0 + (float)v1.screenpos.z * w1 + (float)v2.screenpos.z * w2) * wsum); // Depth range test + // TODO: Clear mode? if (!gstate.isModeThrough()) if (z < gstate.getDepthRangeMin() || z > gstate.getDepthRangeMax()) continue; - if (gstate.isColorTestEnabled() && !gstate.isModeClear()) + if (gstate.isColorTestEnabled() && !clearMode) if (!ColorTestPassed(prim_color_rgb)) continue; // TODO: Does a need to be clamped? - if (gstate.isAlphaTestEnabled() && !gstate.isModeClear()) + if (gstate.isAlphaTestEnabled() && !clearMode) if (!AlphaTestPassed(prim_color_a)) continue; - u8 stencil = GetPixelStencil(p.x, p.y); + // In clear mode, it uses the alpha color as stencil. + u8 stencil = clearMode ? prim_color_a : GetPixelStencil(p.x, p.y); // TODO: Is it safe to ignore gstate.isDepthTestEnabled() when clear mode is enabled? - if (!gstate.isModeClear() && (gstate.isStencilTestEnabled() || gstate.isDepthTestEnabled())) { + if (!clearMode && (gstate.isStencilTestEnabled() || gstate.isDepthTestEnabled())) { if (gstate.isStencilTestEnabled() && !StencilTestPassed(stencil)) { stencil = ApplyStencilOp(gstate.getStencilOpSFail(), p.x, p.y); SetPixelStencil(p.x, p.y, stencil); @@ -943,37 +1049,201 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& if (gstate.isDepthTestEnabled() && gstate.isDepthWriteEnabled()) { SetPixelDepth(p.x, p.y, z); } - } else if (gstate.isModeClear() && gstate.isClearModeDepthWriteEnabled()) { + } else if (clearMode && gstate.isClearModeDepthMask()) { SetPixelDepth(p.x, p.y, z); } - if (gstate.isAlphaBlendEnabled() && !gstate.isModeClear()) { + if (gstate.isAlphaBlendEnabled() && !clearMode) { Vec4 dst = Vec4::FromRGBA(GetPixelColor(p.x, p.y)); prim_color_rgb = AlphaBlendingResult(prim_color_rgb, prim_color_a, dst); } - prim_color_rgb = prim_color_rgb.Clamp(0, 255); + if (!clearMode) + prim_color_rgb = prim_color_rgb.Clamp(0, 255); u32 new_color = Vec4(prim_color_rgb.r(), prim_color_rgb.g(), prim_color_rgb.b(), stencil).ToRGBA(); u32 old_color = GetPixelColor(p.x, p.y); // TODO: Is alpha blending still performed if logic ops are enabled? - if (gstate.isLogicOpEnabled() && !gstate.isModeClear()) { + if (gstate.isLogicOpEnabled() && !clearMode) { // Logic ops don't affect stencil. new_color = (stencil << 24) | (ApplyLogicOp(gstate.getLogicOp(), old_color, new_color) & 0x00FFFFFF); } - if (gstate.isModeClear()) { + if (clearMode) { new_color = (new_color & ~gstate.getClearModeColorMask()) | (old_color & gstate.getClearModeColorMask()); } else { new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask()); } + // TODO: Dither before or inside SetPixelColor SetPixelColor(p.x, p.y, new_color); } } } } +// Draws triangle, vertices specified in counter-clockwise direction +void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2) +{ + Vec2 d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y); + Vec2 d02((int)v0.screenpos.x - (int)v2.screenpos.x, (int)v0.screenpos.y - (int)v2.screenpos.y); + Vec2 d12((int)v1.screenpos.x - (int)v2.screenpos.x, (int)v1.screenpos.y - (int)v2.screenpos.y); + + // Drop primitives which are not in CCW order by checking the cross product + if (d01.x * d02.y - d01.y * d02.x < 0) + return; + + // Is the division and multiplication just &= ~0xF ? + int minX = std::min(std::min(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) / 16 * 16; + int minY = std::min(std::min(v0.screenpos.y, v1.screenpos.y), v2.screenpos.y) / 16 * 16; + int maxX = std::max(std::max(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) / 16 * 16; + int maxY = std::max(std::max(v0.screenpos.y, v1.screenpos.y), v2.screenpos.y) / 16 * 16; + + DrawingCoords scissorTL(gstate.getScissorX1(), gstate.getScissorY1(), 0); + DrawingCoords scissorBR(gstate.getScissorX2(), gstate.getScissorY2(), 0); + minX = std::max(minX, (int)TransformUnit::DrawingToScreen(scissorTL).x); + maxX = std::min(maxX, (int)TransformUnit::DrawingToScreen(scissorBR).x); + minY = std::max(minY, (int)TransformUnit::DrawingToScreen(scissorTL).y); + maxY = std::min(maxY, (int)TransformUnit::DrawingToScreen(scissorBR).y); + + int range = (maxY - minY) / 16 + 1; + if (gstate.isModeClear()) + GlobalThreadPool::Loop(std::bind(&DrawTriangleSlice, v0, v1, v2, minX, minY, maxX, maxY, placeholder::_1, placeholder::_2), 0, range); + else + GlobalThreadPool::Loop(std::bind(&DrawTriangleSlice, v0, v1, v2, minX, minY, maxX, maxY, placeholder::_1, placeholder::_2), 0, range); +} + +void DrawPixel(ScreenCoords pos, Vec3 prim_color_rgb, int prim_color_a, Vec3 sec_color) { + // TODO: Texturing, blending etc. + ScreenCoords scissorTL(TransformUnit::DrawingToScreen(DrawingCoords(gstate.getScissorX1(), gstate.getScissorY1(), 0))); + ScreenCoords scissorBR(TransformUnit::DrawingToScreen(DrawingCoords(gstate.getScissorX2(), gstate.getScissorY2(), 0))); + + if (pos.x < scissorTL.x || pos.y < scissorTL.y || pos.x >= scissorBR.x || pos.y >= scissorBR.y) + return; + + bool clearMode = gstate.isModeClear(); + + // TODO: Abstract out texture mapping so we can insert it here. Too big to duplicate. + if (gstate.isColorDoublingEnabled() && !clearMode) { + // TODO: Do we need to clamp here? + prim_color_rgb *= 2; + sec_color *= 2; + } + + if (!clearMode) + prim_color_rgb += sec_color; + + ScreenCoords pprime = pos; + + // TODO: Fogging + DrawingCoords p = TransformUnit::ScreenToDrawing(pprime); + u16 z = pos.z; + + // Depth range test + // TODO: Clear mode? + if (!gstate.isModeThrough()) + if (z < gstate.getDepthRangeMin() || z > gstate.getDepthRangeMax()) + return; + + if (gstate.isColorTestEnabled() && !clearMode) + if (!ColorTestPassed(prim_color_rgb)) + return; + + // TODO: Does a need to be clamped? + if (gstate.isAlphaTestEnabled() && !clearMode) + if (!AlphaTestPassed(prim_color_a)) + return; + + // In clear mode, it uses the alpha color as stencil. + u8 stencil = clearMode ? prim_color_a : GetPixelStencil(p.x, p.y); + // TODO: Is it safe to ignore gstate.isDepthTestEnabled() when clear mode is enabled? + if (!clearMode && (gstate.isStencilTestEnabled() || gstate.isDepthTestEnabled())) { + if (gstate.isStencilTestEnabled() && !StencilTestPassed(stencil)) { + stencil = ApplyStencilOp(gstate.getStencilOpSFail(), p.x, p.y); + SetPixelStencil(p.x, p.y, stencil); + return; + } + + // Also apply depth at the same time. If disabled, same as passing. + if (gstate.isDepthTestEnabled() && !DepthTestPassed(p.x, p.y, z)) { + if (gstate.isStencilTestEnabled()) { + stencil = ApplyStencilOp(gstate.getStencilOpZFail(), p.x, p.y); + SetPixelStencil(p.x, p.y, stencil); + } + return; + } else if (gstate.isStencilTestEnabled()) { + stencil = ApplyStencilOp(gstate.getStencilOpZPass(), p.x, p.y); + } + + if (gstate.isDepthTestEnabled() && gstate.isDepthWriteEnabled()) { + SetPixelDepth(p.x, p.y, z); + } + } else if (clearMode && gstate.isClearModeDepthMask()) { + SetPixelDepth(p.x, p.y, z); + } + + if (gstate.isAlphaBlendEnabled() && !clearMode) { + Vec4 dst = Vec4::FromRGBA(GetPixelColor(p.x, p.y)); + prim_color_rgb = AlphaBlendingResult(prim_color_rgb, prim_color_a, dst); + } + if (!clearMode) + prim_color_rgb = prim_color_rgb.Clamp(0, 255); + + u32 new_color = Vec4(prim_color_rgb.r(), prim_color_rgb.g(), prim_color_rgb.b(), stencil).ToRGBA(); + u32 old_color = GetPixelColor(p.x, p.y); + + // TODO: Is alpha blending still performed if logic ops are enabled? + if (gstate.isLogicOpEnabled() && !clearMode) { + // Logic ops don't affect stencil. + new_color = (stencil << 24) | (ApplyLogicOp(gstate.getLogicOp(), old_color, new_color) & 0x00FFFFFF); + } + + if (clearMode) { + new_color = (new_color & ~gstate.getClearModeColorMask()) | (old_color & gstate.getClearModeColorMask()); + } else { + new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask()); + } + + SetPixelColor(p.x, p.y, new_color); +} + +void DrawPoint(const VertexData &v0) +{ + DrawPixel(v0.screenpos, v0.color0.rgb(), v0.color0.a(), v0.color1); +} + +void DrawLine(const VertexData &v0, const VertexData &v1) +{ + // TODO: Use a proper line drawing algorithm that handles fractional endpoints correctly. + Vec3 a(v0.screenpos.x, v0.screenpos.y, v0.screenpos.z); + Vec3 b(v1.screenpos.x, v1.screenpos.y, v0.screenpos.z); + + int dx = b.x - a.x; + int dy = b.y - a.y; + int dz = b.z - a.z; + + int steps; + if (abs(dx) < abs(dy)) + steps = dy; + else + steps = dx; + + float xinc = (float)dx / steps; + float yinc = (float)dy / steps; + float zinc = (float)dz / steps; + + float x = a.x; + float y = a.y; + float z = a.z; + for (; steps >= 0; steps--) { + // TODO: interpolate color and UV over line + DrawPixel(ScreenCoords(x, y, z), v0.color0.rgb(), v0.color0.a(), v0.color1); + x = x + xinc; + y = y + yinc; + z = z + zinc; + } +} + bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT); diff --git a/GPU/Software/Rasterizer.h b/GPU/Software/Rasterizer.h index ace598c4e5..66f0570bef 100644 --- a/GPU/Software/Rasterizer.h +++ b/GPU/Software/Rasterizer.h @@ -25,6 +25,8 @@ namespace Rasterizer { // Draws a triangle if its vertices are specified in counter-clockwise order void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2); +void DrawPoint(const VertexData &v0); +void DrawLine(const VertexData &v0, const VertexData &v1); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentTexture(GPUDebugBuffer &buffer); diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 24044d6e9c..8f3136db53 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -19,6 +19,7 @@ #include "GPU/GPUState.h" #include "GPU/ge_constants.h" #include "GPU/Common/TextureDecoder.h" +#include "Core/Debugger/Breakpoints.h" #include "Core/MemMap.h" #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" @@ -60,9 +61,9 @@ GLuint OpenGL_CompileProgram(const char* vertexShader, const char* fragmentShade GLsizei stringBufferUsage = 0; glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result); glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer); - if(Result && stringBufferUsage) { + if (Result && stringBufferUsage) { // not nice - } else if(!Result) { + } else if (!Result) { // not nice } else { // not nice @@ -77,9 +78,9 @@ GLuint OpenGL_CompileProgram(const char* vertexShader, const char* fragmentShade #if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &Result); glGetShaderInfoLog(fragmentShaderID, 1024, &stringBufferUsage, stringBuffer); - if(Result && stringBufferUsage) { + if (Result && stringBufferUsage) { // not nice - } else if(!Result) { + } else if (!Result) { // not nice } else { // not nice @@ -95,9 +96,9 @@ GLuint OpenGL_CompileProgram(const char* vertexShader, const char* fragmentShade #if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) glGetProgramiv(programID, GL_LINK_STATUS, &Result); glGetProgramInfoLog(programID, 1024, &stringBufferUsage, stringBuffer); - if(Result && stringBufferUsage) { + if (Result && stringBufferUsage) { // not nice - } else if(!Result && !shader_errors) { + } else if (!Result && !shader_errors) { // not nice } #endif @@ -327,11 +328,13 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) "RECTANGLES=6,", }; - if (type != GE_PRIM_TRIANGLES && type != GE_PRIM_TRIANGLE_STRIP && type != GE_PRIM_TRIANGLE_FAN && type != GE_PRIM_RECTANGLES) { + /* + if (type == GE_PRIM_POINTS || type == GE_PRIM_LINES || type == GE_PRIM_LINE_STRIP) { ERROR_LOG_REPORT(G3D, "Software: DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); cyclesExecuted += EstimatePerVertexCost() * count; break; } + */ if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { ERROR_LOG_REPORT(G3D, "Software: Bad vertex address %08x!", gstate_c.vertexAddr); @@ -349,8 +352,19 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) } cyclesExecuted += EstimatePerVertexCost() * count; - if (!(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME)) { - TransformUnit::SubmitPrimitive(verts, indices, type, count, gstate.vertType); + int bytesRead; + TransformUnit::SubmitPrimitive(verts, indices, type, count, gstate.vertType, &bytesRead); + + // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). + // Some games rely on this, they don't bother reloading VADDR and IADDR. + // Q: Are these changed reflected in the real registers? Needs testing. + if (indices) { + int indexSize = 1; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT) + indexSize = 2; + gstate_c.indexAddr += count * indexSize; + } else { + gstate_c.vertexAddr += bytesRead; } } break; @@ -551,6 +565,11 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) memcpy(dst, src, width * bpp); } +#ifndef USING_GLES2 + CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); +#endif + break; } diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index b84071fad8..d5f51b8bb9 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -23,12 +23,21 @@ #include "Clipper.h" #include "Lighting.h" +static u8 buf[65536 * 48]; // yolo +static bool outside_range_flag = false; + WorldCoords TransformUnit::ModelToWorld(const ModelCoords& coords) { Mat3x3 world_matrix(gstate.worldMatrix); return WorldCoords(world_matrix * coords) + Vec3(gstate.worldMatrix[9], gstate.worldMatrix[10], gstate.worldMatrix[11]); } +WorldCoords TransformUnit::ModelToWorldNormal(const ModelCoords& coords) +{ + Mat3x3 world_matrix(gstate.worldMatrix); + return WorldCoords(world_matrix * coords); +} + ViewCoords TransformUnit::WorldToView(const WorldCoords& coords) { Mat3x3 view_matrix(gstate.viewMatrix); @@ -42,8 +51,6 @@ ClipCoords TransformUnit::ViewToClip(const ViewCoords& coords) return ClipCoords(projection_matrix * coords4); } -static bool outside_range_flag = false; - // TODO: This is ugly static inline ScreenCoords ClipToScreenInternal(const ClipCoords& coords, bool set_flag = true) { @@ -61,8 +68,10 @@ static inline ScreenCoords ClipToScreenInternal(const ClipCoords& coords, bool s float retz = coords.z * vpz1 / coords.w + vpz2; if (gstate.clipEnable & 0x1) { - if (retz < 0.f) retz = 0.f; - if (retz > 65535.f) retz = 65535.f; + if (retz < 0.f) + retz = 0.f; + if (retz > 65535.f) + retz = 65535.f; } if (set_flag && (retx > 4095.9375f || rety > 4096.9375f || retx < 0 || rety < 0 || retz < 0 || retz > 65535.f)) @@ -81,8 +90,8 @@ DrawingCoords TransformUnit::ScreenToDrawing(const ScreenCoords& coords) { DrawingCoords ret; // TODO: What to do when offset > coord? - ret.x = (((u32)coords.x - gstate.getOffsetX16())/16) & 0x3ff; - ret.y = (((u32)coords.y - gstate.getOffsetY16())/16) & 0x3ff; + ret.x = (((u32)coords.x - gstate.getOffsetX16()) / 16) & 0x3ff; + ret.y = (((u32)coords.y - gstate.getOffsetY16()) / 16) & 0x3ff; ret.z = coords.z; return ret; } @@ -128,9 +137,9 @@ static VertexData ReadVertex(VertexReader& vreader) for (int i = 0; i < vertTypeGetNumBoneWeights(gstate.vertType); ++i) { Mat3x3 bone(&gstate.boneMatrix[12*i]); - tmppos += W[i] * (bone * ModelCoords(pos[0], pos[1], pos[2]) + Vec3(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11])); + tmppos += (bone * ModelCoords(pos[0], pos[1], pos[2]) * W[i] + Vec3(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11])); if (vreader.hasNormal()) - tmpnrm += W[i] * (bone * vertex.normal); + tmpnrm += (bone * vertex.normal) * W[i]; } pos[0] = tmppos.x; @@ -163,8 +172,9 @@ static VertexData ReadVertex(VertexReader& vreader) vertex.screenpos = ClipToScreenInternal(vertex.clippos); if (vreader.hasNormal()) { - vertex.worldnormal = TransformUnit::ModelToWorld(vertex.normal) - Vec3(gstate.worldMatrix[9], gstate.worldMatrix[10], gstate.worldMatrix[11]); - vertex.worldnormal /= vertex.worldnormal.Length(); // TODO: Shouldn't be necessary.. + vertex.worldnormal = TransformUnit::ModelToWorldNormal(vertex.normal); + // TODO: Isn't there a flag that controls whether to normalize the normal? + vertex.worldnormal /= vertex.worldnormal.Length(); } Lighting::Process(vertex); @@ -218,10 +228,10 @@ void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_ for (int point = 0; point < 16; ++point) { int idx = (patch_u + point%4) + (patch_v + point/4) * count_u; - if (indices) - vreader.Goto(indices_16bit ? indices16[idx] : indices8[idx]); - else - vreader.Goto(idx); + if (indices) + vreader.Goto(indices_16bit ? indices16[idx] : indices8[idx]); + else + vreader.Goto(idx); patch.points[point] = ReadVertex(vreader); } @@ -262,14 +272,21 @@ void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_ host->GPUNotifyDraw(); } -void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type) +void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type, int *bytesRead) { // TODO: Cache VertexDecoder objects VertexDecoder vdecoder; vdecoder.SetVertexType(vertex_type); const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt(); - static u8 buf[65536 * 48]; // yolo + if (bytesRead) + *bytesRead = vertex_count * vdecoder.VertexSize(); + + // Frame skipping. + if (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) { + return; + } + u16 index_lower_bound = 0; u16 index_upper_bound = vertex_count - 1; bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT; @@ -283,125 +300,174 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type const int max_vtcs_per_prim = 3; int vtcs_per_prim = 0; - if (prim_type == GE_PRIM_POINTS) vtcs_per_prim = 1; - else if (prim_type == GE_PRIM_LINES) vtcs_per_prim = 2; - else if (prim_type == GE_PRIM_TRIANGLES) vtcs_per_prim = 3; - else if (prim_type == GE_PRIM_RECTANGLES) vtcs_per_prim = 2; - else { - // TODO: Unsupported + + switch (prim_type) { + case GE_PRIM_POINTS: vtcs_per_prim = 1; break; + case GE_PRIM_LINES: vtcs_per_prim = 2; break; + case GE_PRIM_TRIANGLES: vtcs_per_prim = 3; break; + case GE_PRIM_RECTANGLES: vtcs_per_prim = 2; break; } - if (prim_type == GE_PRIM_POINTS || prim_type == GE_PRIM_LINES || prim_type == GE_PRIM_TRIANGLES || prim_type == GE_PRIM_RECTANGLES) { - for (int vtx = 0; vtx < vertex_count; vtx += vtcs_per_prim) { - VertexData data[max_vtcs_per_prim]; + VertexData data[max_vtcs_per_prim]; - for (int i = 0; i < vtcs_per_prim; ++i) { - if (indices) - vreader.Goto(indices_16bit ? indices16[vtx+i] : indices8[vtx+i]); - else - vreader.Goto(vtx+i); + // TODO: Do this in two passes - first process the vertices (before indexing/stripping), + // then resolve the indices. This lets us avoid transforming shared vertices twice. - data[i] = ReadVertex(vreader); - if (outside_range_flag) + switch (prim_type) { + case GE_PRIM_POINTS: + case GE_PRIM_LINES: + case GE_PRIM_TRIANGLES: + case GE_PRIM_RECTANGLES: + { + for (int vtx = 0; vtx < vertex_count; vtx += vtcs_per_prim) { + for (int i = 0; i < vtcs_per_prim; ++i) { + if (indices) + vreader.Goto(indices_16bit ? indices16[vtx+i] : indices8[vtx+i]); + else + vreader.Goto(vtx+i); + + data[i] = ReadVertex(vreader); + if (outside_range_flag) + break; + } + if (outside_range_flag) { + outside_range_flag = false; + continue; + } + + switch (prim_type) { + case GE_PRIM_TRIANGLES: + { + if (!gstate.isCullEnabled() || gstate.isModeClear()) { + Clipper::ProcessTriangle(data[0], data[1], data[2]); + Clipper::ProcessTriangle(data[2], data[1], data[0]); + } else if (!gstate.getCullMode()) + Clipper::ProcessTriangle(data[2], data[1], data[0]); + else + Clipper::ProcessTriangle(data[0], data[1], data[2]); break; - } - if (outside_range_flag) { - outside_range_flag = false; - continue; - } + } + case GE_PRIM_RECTANGLES: + Clipper::ProcessQuad(data[0], data[1]); + break; + + case GE_PRIM_LINES: + Clipper::ProcessLine(data[0], data[1]); + break; + + case GE_PRIM_POINTS: + Clipper::ProcessPoint(data[0]); + break; + } + } + break; + } + + case GE_PRIM_LINE_STRIP: + { + int skip_count = 1; // Don't draw a line when loading the first vertex + for (int vtx = 0; vtx < vertex_count; ++vtx) { + if (indices) + vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]); + else + vreader.Goto(vtx); + + data[vtx & 1] = ReadVertex(vreader); + if (outside_range_flag) { + // Drop all primitives containing the current vertex + skip_count = 2; + outside_range_flag = false; + continue; + } + + if (skip_count) { + --skip_count; + } else { + Clipper::ProcessLine(data[(vtx & 1) ^ 1], data[vtx & 1]); + } + } + break; + } + + case GE_PRIM_TRIANGLE_STRIP: + { + int skip_count = 2; // Don't draw a triangle when loading the first two vertices + + for (int vtx = 0; vtx < vertex_count; ++vtx) { + if (indices) + vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]); + else + vreader.Goto(vtx); + + data[vtx % 3] = ReadVertex(vreader); + if (outside_range_flag) { + // Drop all primitives containing the current vertex + skip_count = 2; + outside_range_flag = false; + continue; + } + + if (skip_count) { + --skip_count; + continue; + } - switch (prim_type) { - case GE_PRIM_TRIANGLES: - { if (!gstate.isCullEnabled() || gstate.isModeClear()) { Clipper::ProcessTriangle(data[0], data[1], data[2]); Clipper::ProcessTriangle(data[2], data[1], data[0]); - } else if (!gstate.getCullMode()) + } else if ((!gstate.getCullMode()) ^ (vtx % 2)) { + // We need to reverse the vertex order for each second primitive, + // but we additionally need to do that for every primitive if CCW cullmode is used. Clipper::ProcessTriangle(data[2], data[1], data[0]); - else + } else { Clipper::ProcessTriangle(data[0], data[1], data[2]); - break; - } - - case GE_PRIM_RECTANGLES: - Clipper::ProcessQuad(data[0], data[1]); - break; + } } + break; } - } else if (prim_type == GE_PRIM_TRIANGLE_STRIP) { - VertexData data[3]; - unsigned int skip_count = 2; // Don't draw a triangle when loading the first two vertices - for (int vtx = 0; vtx < vertex_count; ++vtx) { + case GE_PRIM_TRIANGLE_FAN: + { + unsigned int skip_count = 1; // Don't draw a triangle when loading the first two vertices + if (indices) - vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]); + vreader.Goto(indices_16bit ? indices16[0] : indices8[0]); else - vreader.Goto(vtx); + vreader.Goto(0); + data[0] = ReadVertex(vreader); - data[vtx % 3] = ReadVertex(vreader); - if (outside_range_flag) { - // Drop all primitives containing the current vertex - skip_count = 2; - outside_range_flag = false; - continue; - } - - if (skip_count) { - --skip_count; - continue; - } - - if (!gstate.isCullEnabled() || gstate.isModeClear()) { - Clipper::ProcessTriangle(data[0], data[1], data[2]); - Clipper::ProcessTriangle(data[2], data[1], data[0]); - } else if ((!gstate.getCullMode()) ^ (vtx % 2)) { - // We need to reverse the vertex order for each second primitive, - // but we additionally need to do that for every primitive if CCW cullmode is used. - Clipper::ProcessTriangle(data[2], data[1], data[0]); - } else { - Clipper::ProcessTriangle(data[0], data[1], data[2]); - } - } - } else if (prim_type == GE_PRIM_TRIANGLE_FAN) { - VertexData data[3]; - unsigned int skip_count = 1; // Don't draw a triangle when loading the first two vertices - - if (indices) - vreader.Goto(indices_16bit ? indices16[0] : indices8[0]); - else - vreader.Goto(0); - data[0] = ReadVertex(vreader); - - for (int vtx = 1; vtx < vertex_count; ++vtx) { - if (indices) - vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]); - else - vreader.Goto(vtx); - - data[2 - (vtx % 2)] = ReadVertex(vreader); - if (outside_range_flag) { - // Drop all primitives containing the current vertex - skip_count = 2; - outside_range_flag = false; - continue; - } - - if (skip_count) { - --skip_count; - continue; - } - - if (!gstate.isCullEnabled() || gstate.isModeClear()) { - Clipper::ProcessTriangle(data[0], data[1], data[2]); - Clipper::ProcessTriangle(data[2], data[1], data[0]); - } else if ((!gstate.getCullMode()) ^ (vtx % 2)) { - // We need to reverse the vertex order for each second primitive, - // but we additionally need to do that for every primitive if CCW cullmode is used. - Clipper::ProcessTriangle(data[2], data[1], data[0]); - } else { - Clipper::ProcessTriangle(data[0], data[1], data[2]); + for (int vtx = 1; vtx < vertex_count; ++vtx) { + if (indices) + vreader.Goto(indices_16bit ? indices16[vtx] : indices8[vtx]); + else + vreader.Goto(vtx); + + data[2 - (vtx % 2)] = ReadVertex(vreader); + if (outside_range_flag) { + // Drop all primitives containing the current vertex + skip_count = 2; + outside_range_flag = false; + continue; + } + + if (skip_count) { + --skip_count; + continue; + } + + if (!gstate.isCullEnabled() || gstate.isModeClear()) { + Clipper::ProcessTriangle(data[0], data[1], data[2]); + Clipper::ProcessTriangle(data[2], data[1], data[0]); + } else if ((!gstate.getCullMode()) ^ (vtx % 2)) { + // We need to reverse the vertex order for each second primitive, + // but we additionally need to do that for every primitive if CCW cullmode is used. + Clipper::ProcessTriangle(data[2], data[1], data[0]); + } else { + Clipper::ProcessTriangle(data[0], data[1], data[2]); + } } + break; } } diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index b36cfb49c0..ba616cc30d 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -108,6 +108,7 @@ struct VertexData class TransformUnit { public: + static WorldCoords ModelToWorldNormal(const ModelCoords& coords); static WorldCoords ModelToWorld(const ModelCoords& coords); static ViewCoords WorldToView(const WorldCoords& coords); static ClipCoords ViewToClip(const ViewCoords& coords); @@ -116,5 +117,5 @@ public: static ScreenCoords DrawingToScreen(const DrawingCoords& coords); static void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type); - static void SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type); + static void SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type, int *bytesRead); }; diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index bf0623e8d2..677697265c 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -469,6 +469,9 @@ enum GETexFunc GE_TEXFUNC_BLEND = 2, GE_TEXFUNC_REPLACE = 3, GE_TEXFUNC_ADD = 4, + GE_TEXFUNC_UNKNOWN1 = 5, + GE_TEXFUNC_UNKNOWN2 = 6, + GE_TEXFUNC_UNKNOWN3 = 7, }; enum GEStencilOp diff --git a/Qt/Common.pro b/Qt/Common.pro index f817c67f33..51a503fa20 100755 --- a/Qt/Common.pro +++ b/Qt/Common.pro @@ -6,58 +6,56 @@ CONFIG += staticlib include(Settings.pri) +# CPU arm { - SOURCES += ../Common/ArmCPUDetect.cpp \ - ../Common/ArmEmitter.cpp \ - ../Common/ArmThunk.cpp - HEADERS += ../Common/ArmEmitter.h + SOURCES += $$P/Common/ArmCPUDetect.cpp \ + $$P/Common/ArmEmitter.cpp \ + $$P/Common/ArmThunk.cpp + HEADERS += $$P/Common/ArmEmitter.h } x86 { - SOURCES += ../Common/ABI.cpp \ - ../Common/CPUDetect.cpp \ - ../Common/Thunk.cpp \ - ../Common/x64Analyzer.cpp \ - ../Common/x64Emitter.cpp - HEADERS += ../Common/ABI.h \ - ../Common/CPUDetect.h \ - ../Common/Thunk.h \ - ../Common/x64Analyzer.h \ - ../Common/x64Emitter.h + SOURCES += $$P/Common/ABI.cpp \ + $$P/Common/CPUDetect.cpp \ + $$P/Common/Thunk.cpp \ + $$P/Common/x64Analyzer.cpp \ + $$P/Common/x64Emitter.cpp + HEADERS += $$P/Common/ABI.h \ + $$P/Common/Thunk.h \ + $$P/Common/x64Analyzer.h \ + $$P/Common/x64Emitter.h } +HEADERS += $$P/Common/CPUDetect.h + win32 { - SOURCES += ../Common/stdafx.cpp - HEADERS += ../Common/stdafx.h + SOURCES += $$P/Common/stdafx.cpp + HEADERS += $$P/Common/stdafx.h } -SOURCES += ../Common/ChunkFile.cpp \ - ../Common/ConsoleListener.cpp \ - ../Common/FileUtil.cpp \ - ../Common/LogManager.cpp \ - ../Common/KeyMap.cpp \ - ../Common/MathUtil.cpp \ - ../Common/MemArena.cpp \ - ../Common/MemoryUtil.cpp \ - ../Common/Misc.cpp \ - ../Common/MsgHandler.cpp \ - ../Common/StringUtils.cpp \ - ../Common/Thread.cpp \ - ../Common/ThreadPools.cpp \ - ../Common/Timer.cpp \ - ../Common/Crypto/*.cpp -HEADERS += ../Common/ChunkFile.h \ - ../Common/ConsoleListener.h \ - ../Common/FileUtil.h \ - ../Common/LogManager.h \ - ../Common/KeyMap.h \ - ../Common/MathUtil.h \ - ../Common/MemArena.h \ - ../Common/MemoryUtil.h \ - ../Common/MsgHandler.h \ - ../Common/StringUtils.h \ - ../Common/Thread.h \ - ../Common/ThreadPools.h \ - ../Common/Timer.h \ - ../Common/Crypto/*.h +SOURCES += $$P/Common/ChunkFile.cpp \ + $$P/Common/ConsoleListener.cpp \ + $$P/Common/FileUtil.cpp \ + $$P/Common/LogManager.cpp \ + $$P/Common/KeyMap.cpp \ + $$P/Common/MemArena.cpp \ + $$P/Common/MemoryUtil.cpp \ + $$P/Common/Misc.cpp \ + $$P/Common/MsgHandler.cpp \ + $$P/Common/StringUtils.cpp \ + $$P/Common/ThreadPools.cpp \ + $$P/Common/Timer.cpp \ + $$P/Common/Crypto/*.cpp +HEADERS += $$P/Common/ChunkFile.h \ + $$P/Common/ConsoleListener.h \ + $$P/Common/FileUtil.h \ + $$P/Common/LogManager.h \ + $$P/Common/KeyMap.h \ + $$P/Common/MemArena.h \ + $$P/Common/MemoryUtil.h \ + $$P/Common/MsgHandler.h \ + $$P/Common/StringUtils.h \ + $$P/Common/ThreadPools.h \ + $$P/Common/Timer.h \ + $$P/Common/Crypto/*.h -INCLUDEPATH += ../native +INCLUDEPATH += $$P/native diff --git a/Qt/Core.pro b/Qt/Core.pro index b566e36f9d..9a3e22f6d4 100755 --- a/Qt/Core.pro +++ b/Qt/Core.pro @@ -4,90 +4,91 @@ TARGET = Core TEMPLATE = lib CONFIG += staticlib -version.target = ../git-version.cpp -!contains(MEEGO_EDITION,harmattan):contains(QMAKE_HOST.os, "Windows") { version.commands = $$PWD/../Windows/git-version-gen.cmd } -else { version.commands = $$PWD/git-version-gen.sh } -version.depends = ../.git - -QMAKE_EXTRA_TARGETS += version -PRE_TARGETDEPS += ../git-version.cpp -SOURCES += ../git-version.cpp - include(Settings.pri) -INCLUDEPATH += ../native ../Core/MIPS ../ ../ext/xbrz +INCLUDEPATH += $$P/native $$P/Core/MIPS $$P/ $$P/ext/xbrz arm { - SOURCES += ../Core/MIPS/ARM/*.cpp \ #CoreARM - ../ext/disarm.cpp - HEADERS += ../Core/MIPS/ARM/*.h + SOURCES += $$P/Core/MIPS/ARM/*.cpp \ #CoreARM + $$P/ext/disarm.cpp + HEADERS += $$P/Core/MIPS/ARM/*.h } x86 { - SOURCES += ../Core/MIPS/x86/*.cpp - HEADERS += ../Core/MIPS/x86/*.h + SOURCES += $$P/Core/MIPS/x86/*.cpp + HEADERS += $$P/Core/MIPS/x86/*.h } win32 { - SOURCES += ../Windows/OpenGLBase.cpp - HEADERS += ../Windows/OpenGLBase.h + SOURCES += $$P/Windows/OpenGLBase.cpp + HEADERS += $$P/Windows/OpenGLBase.h - SOURCES += ../GPU/Directx9/helper/*.cpp - HEADERS += ../GPU/Directx9/helper/*.h + SOURCES += $$P/GPU/Directx9/helper/*.cpp + HEADERS += $$P/GPU/Directx9/helper/*.h - SOURCES += ../GPU/Directx9/*.cpp - HEADERS += ../GPU/Directx9/*.h - INCLUDEPATH += ../dx9sdk/Include + SOURCES += $$P/GPU/Directx9/*.cpp + HEADERS += $$P/GPU/Directx9/*.h + INCLUDEPATH += $$P/dx9sdk/Include } -SOURCES += ../Core/*.cpp \ # Core - ../Core/Debugger/*.cpp \ - ../Core/Dialog/*.cpp \ - ../Core/ELF/*.cpp \ - ../Core/FileSystems/*.cpp \ - ../Core/Font/*.cpp \ - ../Core/HLE/*.cpp \ - ../Core/HW/*.cpp \ - ../Core/MIPS/*.cpp \ - ../Core/MIPS/JitCommon/*.cpp \ - ../Core/Util/*.cpp \ - ../GPU/GeDisasm.cpp \ # GPU - ../GPU/GPUCommon.cpp \ - ../GPU/GPUState.cpp \ - ../GPU/Math3D.cpp \ - ../GPU/Null/NullGpu.cpp \ - ../GPU/GLES/*.cpp \ - ../GPU/Common/IndexGenerator.cpp \ - ../GPU/Common/TextureDecoder.cpp \ - ../GPU/Common/VertexDecoderCommon.cpp \ - ../GPU/Common/PostShader.cpp \ - ../ext/libkirk/*.c \ # Kirk - ../ext/xxhash.c \ # xxHash - ../ext/xbrz/*.cpp # XBRZ +SOURCES += $$P/Core/*.cpp \ # Core + $$P/Core/Debugger/*.cpp \ + $$P/Core/Dialog/*.cpp \ + $$P/Core/ELF/*.cpp \ + $$P/Core/FileSystems/*.cpp \ + $$P/Core/Font/*.cpp \ + $$P/Core/HLE/*.cpp \ + $$P/Core/HW/*.cpp \ + $$P/Core/MIPS/*.cpp \ + $$P/Core/MIPS/JitCommon/*.cpp \ + $$P/Core/Util/*.cpp \ + $$P/GPU/GeDisasm.cpp \ # GPU + $$P/GPU/GPUCommon.cpp \ + $$P/GPU/GPUState.cpp \ + $$P/GPU/Math3D.cpp \ + $$P/GPU/Null/NullGpu.cpp \ + $$P/GPU/GLES/FragmentShaderGenerator.cpp \ + $$P/GPU/GLES/Framebuffer.cpp \ + $$P/GPU/GLES/GLES_GPU.cpp \ + $$P/GPU/GLES/ShaderManager.cpp \ + $$P/GPU/GLES/SoftwareTransform.cpp \ + $$P/GPU/GLES/Spline.cpp \ + $$P/GPU/GLES/StateMapping.cpp \ + $$P/GPU/GLES/TextureCache.cpp \ + $$P/GPU/GLES/TextureScaler.cpp \ + $$P/GPU/GLES/TransformPipeline.cpp \ + $$P/GPU/GLES/VertexDecoder.cpp \ + $$P/GPU/GLES/VertexShaderGenerator.cpp \ + $$P/GPU/Software/*.cpp \ + $$P/GPU/Common/IndexGenerator.cpp \ + $$P/GPU/Common/TextureDecoder.cpp \ + $$P/GPU/Common/VertexDecoderCommon.cpp \ + $$P/GPU/Common/PostShader.cpp \ + $$P/ext/libkirk/*.c \ # Kirk + $$P/ext/xxhash.c \ # xxHash + $$P/ext/xbrz/*.cpp # XBRZ -!x86:!symbian { - SOURCES += ../GPU/Common/TextureDecoderNEON.cpp -} +!x86:!symbian: SOURCES += $$P/GPU/Common/TextureDecoderNEON.cpp -# Software GPU -!symbian { - SOURCES += ../GPU/Software/*.cpp - HEADERS += ../GPU/Software/*.h -} +arm: SOURCES += $$P/GPU/GLES/VertexDecoderArm.cpp +else:SOURCES += $$P/GPU/GLES/VertexDecoderX86.cpp -HEADERS += ../Core/*.h \ - ../Core/Debugger/*.h \ - ../Core/Dialog/*.h \ - ../Core/ELF/*.h \ - ../Core/FileSystems/*.h \ - ../Core/Font/*.h \ - ../Core/HLE/*.h \ - ../Core/HW/*.h \ - ../Core/MIPS/*.h \ - ../Core/MIPS/JitCommon/*.h \ - ../Core/Util/*.h \ - ../GPU/GLES/*.h \ - ../GPU/Common/*.h \ - ../GPU/*.h \ - ../ext/libkirk/*.h \ - ../ext/xbrz/*.h +HEADERS += $$P/Core/*.h \ + $$P/Core/Debugger/*.h \ + $$P/Core/Dialog/*.h \ + $$P/Core/ELF/*.h \ + $$P/Core/FileSystems/*.h \ + $$P/Core/Font/*.h \ + $$P/Core/HLE/*.h \ + $$P/Core/HW/*.h \ + $$P/Core/MIPS/*.h \ + $$P/Core/MIPS/JitCommon/*.h \ + $$P/Core/Util/*.h \ + $$P/GPU/GLES/*.h \ + $$P/GPU/Software/*.h \ + $$P/GPU/Common/*.h \ + $$P/GPU/*.h \ + $$P/ext/libkirk/*.h \ + $$P/ext/xbrz/*.h + +win32: INCLUDEPATH += $$P/ffmpeg/WindowsInclude diff --git a/Qt/EmuThread.cpp b/Qt/EmuThread.cpp deleted file mode 100644 index 8d23515c84..0000000000 --- a/Qt/EmuThread.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "EmuThread.h" -#include "Core/System.h" - -#include - -void EmuThread_LockDraw(bool value) -{ - // left there just to avoid compilation problems, this is called a lot - // in debuggers -} - -QString GetCurrentFilename() -{ - return QString::fromStdString(PSP_CoreParameter().fileToStart); -} diff --git a/Qt/EmuThread.h b/Qt/EmuThread.h deleted file mode 100644 index 0665d0160e..0000000000 --- a/Qt/EmuThread.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -void EmuThread_LockDraw(bool value); -QString GetCurrentFilename(); diff --git a/Qt/Native.pro b/Qt/Native.pro index 9fb2290550..4c478e5543 100755 --- a/Qt/Native.pro +++ b/Qt/Native.pro @@ -7,123 +7,137 @@ CONFIG += staticlib include(Settings.pri) !mobile_platform: { - SOURCES += ../native/ext/glew/glew.c - HEADERS += ../native/ext/glew/GL/*.h + SOURCES += $$P/native/ext/glew/glew.c + HEADERS += $$P/native/ext/glew/GL/*.h } # Backtrace x86:!mobile_platform: { - SOURCES += ../native/base/backtrace.cpp - HEADERS += ../native/base/backtrace.h + SOURCES += $$P/native/base/backtrace.cpp + HEADERS += $$P/native/base/backtrace.h } # RG_ETC1 -SOURCES += ../native/ext/rg_etc1/rg_etc1.cpp -HEADERS += ../native/ext/rg_etc1/rg_etc1.h -INCLUDEPATH += ../native/ext/rg_etc1 +SOURCES += $$P/native/ext/rg_etc1/rg_etc1.cpp +HEADERS += $$P/native/ext/rg_etc1/rg_etc1.h +INCLUDEPATH += $$P/native/ext/rg_etc1 + +# Cityhash + +SOURCES += ../native/ext/cityhash/city.cpp +HEADERS += ../native/ext/cityhash/*.h +INCLUDEPATH += ../native/ext/cityhash # JPGE -SOURCES += ../native/ext/jpge/*.cpp -HEADERS += ../native/ext/jpge/*.h -INCLUDEPATH += ../native/ext/jpge - -# Stb_image - -SOURCES += ../native/ext/stb_image/stb_image.c -HEADERS += ../native/ext/stb_image/stb_image.h -INCLUDEPATH += ../native/ext/stb_image -win32 { - SOURCES += ../native/ext/stb_image_write/stb_image_write.c - HEADERS += ../native/ext/stb_image_write/stb_image_writer.h - INCLUDEPATH += ../native/ext/stb_image_write -} +SOURCES += $$P/native/ext/jpge/*.cpp +HEADERS += $$P/native/ext/jpge/*.h +INCLUDEPATH += $$P/native/ext/jpge # Stb_vorbis -SOURCES += ../native/ext/stb_vorbis/stb_vorbis.c -HEADERS += ../native/ext/stb_vorbis/stb_vorbis.h -INCLUDEPATH += ../native/ext/stb_vorbis +SOURCES += $$P/native/ext/stb_vorbis/stb_vorbis.c +HEADERS += $$P/native/ext/stb_vorbis/stb_vorbis.h +INCLUDEPATH += $$P/native/ext/stb_vorbis # Snappy -SOURCES += ../ext/snappy/*.cpp -HEADERS += ../ext/snappy/*.h -INCLUDEPATH += ../ext/snappy +SOURCES += $$P/ext/snappy/*.cpp +HEADERS += $$P/ext/snappy/*.h +INCLUDEPATH += $$P/ext/snappy + +# VJSON + +SOURCES += $$P/native/ext/vjson/json.cpp \ + $$P/native/ext/vjson/block_allocator.cpp +HEADERS += $$P/native/ext/vjson/json.h \ + $$P/native/ext/vjson/block_allocator.h +INCLUDEPATH += $$P/native/ext/vjson # Zlib -!symbian: { - SOURCES += ../ext/zlib/*.c - HEADERS += ../ext/zlib/*.h +win32|contains(QT_CONFIG, no-zlib) { + SOURCES += $$P/ext/zlib/*.c + HEADERS += $$P/ext/zlib/*.h } +# Libzip +SOURCES += $$P/native/ext/libzip/*.c +HEADERS += $$P/native/ext/libzip/*.h + +# Libpng +SOURCES += $$P/native/ext/libpng16/*.c +HEADERS += $$P/native/ext/libpng16/*.h +INCLUDEPATH += $$P/native/ext + # Native -SOURCES += ../native/audio/*.cpp \ - ../native/base/buffer.cpp \ - ../native/base/colorutil.cpp \ - ../native/base/display.cpp \ - ../native/base/error_context.cpp \ - ../native/base/fastlist_test.cpp \ - ../native/base/stringutil.cpp \ - ../native/base/timeutil.cpp \ - ../native/data/compression.cpp \ - ../native/file/*.cpp \ - ../native/gfx/gl_debug_log.cpp \ - ../native/gfx/gl_lost_manager.cpp \ - ../native/gfx/texture.cpp \ - ../native/gfx/texture_atlas.cpp \ - ../native/gfx/texture_gen.cpp \ - ../native/gfx_es2/*.cpp \ - ../native/gfx_es2/*.c \ - ../native/i18n/*.cpp \ - ../native/image/*.cpp \ - ../native/input/*.cpp \ - ../native/math/curves.cpp \ - ../native/math/expression_parser.cpp \ - ../native/math/math_util.cpp \ - ../native/math/lin/*.cpp \ - ../native/net/*.cpp \ - ../native/profiler/profiler.cpp \ - ../native/thread/*.cpp \ - ../native/ui/*.cpp \ - ../native/util/bits/*.cpp \ - ../native/util/hash/hash.cpp \ - ../native/util/random/perlin.cpp \ - ../native/util/text/utf8.cpp +SOURCES += $$P/native/audio/*.cpp \ + $$P/native/base/buffer.cpp \ + $$P/native/base/colorutil.cpp \ + $$P/native/base/display.cpp \ + $$P/native/base/error_context.cpp \ + $$P/native/base/fastlist_test.cpp \ + $$P/native/base/stringutil.cpp \ + $$P/native/base/timeutil.cpp \ + $$P/native/data/compression.cpp \ + $$P/native/file/*.cpp \ + $$P/native/gfx/gl_debug_log.cpp \ + $$P/native/gfx/gl_lost_manager.cpp \ + $$P/native/gfx/texture.cpp \ + $$P/native/gfx/texture_atlas.cpp \ + $$P/native/gfx/texture_gen.cpp \ + $$P/native/gfx_es2/*.cpp \ + $$P/native/gfx_es2/*.c \ + $$P/native/i18n/*.cpp \ + $$P/native/image/*.cpp \ + $$P/native/input/*.cpp \ + $$P/native/math/curves.cpp \ + $$P/native/math/expression_parser.cpp \ + $$P/native/math/math_util.cpp \ + $$P/native/math/lin/*.cpp \ + $$P/native/net/*.cpp \ + $$P/native/profiler/profiler.cpp \ + $$P/native/thread/*.cpp \ + $$P/native/ui/*.cpp \ + $$P/native/util/bits/*.cpp \ + $$P/native/util/hash/hash.cpp \ + $$P/native/util/random/perlin.cpp \ + $$P/native/util/text/utf8.cpp \ + $$P/native/util/text/parsers.cpp -HEADERS += ../native/audio/*.h \ - ../native/base/basictypes.h \ - ../native/base/buffer.h \ - ../native/base/color.h \ - ../native/base/colorutil.h \ - ../native/base/display.h \ - ../native/base/error_context.h \ - ../native/base/fastlist.h \ - ../native/base/linked_ptr.h \ - ../native/base/logging.h \ - ../native/base/mutex.h \ - ../native/base/scoped_ptr.h \ - ../native/base/stats.h \ - ../native/base/stringutil.h \ - ../native/base/timeutil.h \ - ../native/data/compression.h \ - ../native/file/*.h \ - ../native/gfx/*.h \ - ../native/gfx_es2/*.h \ - ../native/i18n/*.h \ - ../native/image/*.h \ - ../native/input/*.h \ - ../native/math/*.h \ - ../native/math/lin/*.h \ - ../native/net/*.h \ - ../native/profiler/profiler.h \ - ../native/thread/*.h \ - ../native/ui/*.h \ - ../native/util/bits/*.h \ - ../native/util/hash/hash.h \ - ../native/util/random/*.h \ - ../native/util/text/utf8.h -INCLUDEPATH += ../native +HEADERS += $$P/native/audio/*.h \ + $$P/native/base/basictypes.h \ + $$P/native/base/buffer.h \ + $$P/native/base/color.h \ + $$P/native/base/colorutil.h \ + $$P/native/base/display.h \ + $$P/native/base/error_context.h \ + $$P/native/base/fastlist.h \ + $$P/native/base/linked_ptr.h \ + $$P/native/base/logging.h \ + $$P/native/base/mutex.h \ + $$P/native/base/scoped_ptr.h \ + $$P/native/base/stats.h \ + $$P/native/base/stringutil.h \ + $$P/native/base/timeutil.h \ + $$P/native/data/compression.h \ + $$P/native/file/*.h \ + $$P/native/gfx/*.h \ + $$P/native/gfx_es2/*.h \ + $$P/native/i18n/*.h \ + $$P/native/image/*.h \ + $$P/native/input/*.h \ + $$P/native/math/*.h \ + $$P/native/math/lin/*.h \ + $$P/native/net/*.h \ + $$P/native/profiler/profiler.h \ + $$P/native/thread/*.h \ + $$P/native/ui/*.h \ + $$P/native/util/bits/*.h \ + $$P/native/util/hash/hash.h \ + $$P/native/util/random/*.h \ + $$P/native/util/text/utf8.h \ + $$P/native/util/text/parsers.h +INCLUDEPATH += $$P/native diff --git a/Qt/PPSSPP.desktop b/Qt/PPSSPP.desktop index 4473724924..a086e0180d 100644 --- a/Qt/PPSSPP.desktop +++ b/Qt/PPSSPP.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Encoding=UTF-8 -Version=0.9.5 +Version=0.9.6 Type=Application Terminal=false Name=PPSSPP diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index 7784e7759f..5e1d0c6cd3 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -1,93 +1,105 @@ TARGET = PPSSPPQt -VERSION = 0.9.5 # Main Qt modules QT += core gui opengl include(Settings.pri) -# Extra Qt modules -linux: CONFIG += link_pkgconfig -win32|greaterThan(QT_MAJOR_VERSION,4) { - QT += multimedia -} else { - linux:packagesExist(QtMultimedia) { - QT += multimedia - } else { - CONFIG += mobility - MOBILITY += multimedia +lessThan(QT_MAJOR_VERSION, 5) { + lessThan(QT_MAJOR_VERSION, 4) | lessThan(QT_MINOR_VERSION, 7) { + error(PPSSPP requires Qt 4.7 or newer but Qt $$[QT_VERSION] was detected.) } } + +# Extra Qt modules +linux: CONFIG += link_pkgconfig +linux:lessThan(QT_MAJOR_VERSION,5):!packagesExist(QtMultimedia) { + # Ubuntu et al workaround. They forgot QtMultimedia + CONFIG += mobility + MOBILITY += multimedia +} +else: QT += multimedia + greaterThan(QT_MAJOR_VERSION,4): QT += widgets -mobile_platform: MOBILITY += sensors -symbian: MOBILITY += systeminfo feedback +mobile_platform { + CONFIG += mobility + MOBILITY += sensors + symbian: MOBILITY += systeminfo feedback +} # PPSSPP Libs -symbian: XT=".lib" -else: LIBS += -L$$CONFIG_DIR -LIBS += -lCore$${XT} -lCommon$${XT} -lNative$${XT} +QMAKE_LIBDIR += $$CONFIG_DIR +symbian: LIBS += -lCore.lib -lCommon.lib -lNative.lib +else: LIBS += -lCore -lCommon -lNative # FFMPEG Path -win32: FFMPEG_DIR = ../ffmpeg/Windows/$${QMAKE_TARGET.arch}/lib/ -linux: FFMPEG_DIR = ../ffmpeg/linux/$${QMAKE_TARGET.arch}/lib/ -qnx: FFMPEG_DIR = ../ffmpeg/blackberry/armv7/lib/ -symbian:FFMPEG_DIR = -l +win32: QMAKE_LIBDIR += $$P/ffmpeg/Windows/$${QMAKE_TARGET.arch}/lib/ +linux: QMAKE_LIBDIR += $$P/ffmpeg/linux/$${QMAKE_TARGET.arch}/lib/ +macx: QMAKE_LIBDIR += $$P/ffmpeg/macosx/x86_64/lib/ +ios: QMAKE_LIBDIR += $$P/ffmpeg/ios/universal/lib/ +qnx: QMAKE_LIBDIR += $$P/ffmpeg/blackberry/armv7/lib/ +symbian:QMAKE_LIBDIR += $$P/ffmpeg/symbian/armv6/lib/ + +contains(DEFINES, USE_FFMPEG): LIBS += -lavformat -lavcodec -lavutil -lswresample -lswscale # External (platform-dependant) libs -win32|symbian: LIBS += $${FFMPEG_DIR}avformat.lib $${FFMPEG_DIR}avcodec.lib $${FFMPEG_DIR}avutil.lib $${FFMPEG_DIR}swresample.lib $${FFMPEG_DIR}swscale.lib -else: LIBS += $${FFMPEG_DIR}libavformat.a $${FFMPEG_DIR}libavcodec.a $${FFMPEG_DIR}libavutil.a $${FFMPEG_DIR}libswresample.a $${FFMPEG_DIR}libswscale.a win32 { #Use a fixed base-address under windows QMAKE_LFLAGS += /FIXED /BASE:"0x00400000" QMAKE_LFLAGS += /DYNAMICBASE:NO LIBS += -lwinmm -lws2_32 -lShell32 -lAdvapi32 - contains(QMAKE_TARGET.arch, x86_64): LIBS += $$files(../dx9sdk/Lib/x64/*.lib) - else: LIBS += $$files(../dx9sdk/Lib/x86/*.lib) + contains(QMAKE_TARGET.arch, x86_64): LIBS += $$files($$P/dx9sdk/Lib/x64/*.lib) + else: LIBS += $$files($$P/dx9sdk/Lib/x86/*.lib) } linux { LIBS += -ldl - PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a + PRE_TARGETDEPS += $$CONFIG_DIR/libCommon.a $$CONFIG_DIR/libCore.a $$CONFIG_DIR/libNative.a packagesExist(sdl) { DEFINES += QT_HAS_SDL + SOURCES += $$P/SDL/SDLJoystick.cpp + HEADERS += $$P/SDL/SDLJoystick.h PKGCONFIG += sdl } } qnx: LIBS += -lscreen -symbian: LIBS += -llibglib -lRemConCoreApi -lRemConInterfaceBase -# Avoids problems with some compilers -unix:!symbian: LIBS += -lz +symbian: LIBS += -lremconcoreapi -lremconinterfacebase +contains(QT_CONFIG, system-zlib) { + unix: LIBS += -lz +} # Main -SOURCES += ../native/base/QtMain.cpp -HEADERS += ../native/base/QtMain.h +SOURCES += $$P/native/base/QtMain.cpp +HEADERS += $$P/native/base/QtMain.h symbian { - SOURCES += ../native/base/SymbianMediaKeys.cpp - HEADERS += ../native/base/SymbianMediaKeys.h + SOURCES += $$P/native/base/SymbianMediaKeys.cpp + HEADERS += $$P/native/base/SymbianMediaKeys.h } # UI -SOURCES += ../UI/*Screen.cpp \ - ../UI/*Screens.cpp \ - ../UI/GamepadEmu.cpp \ - ../UI/GameInfoCache.cpp \ - ../UI/OnScreenDisplay.cpp \ - ../UI/UIShader.cpp \ - ../android/jni/TestRunner.cpp +SOURCES += $$P/UI/*Screen.cpp \ + $$P/UI/*Screens.cpp \ + $$P/UI/Store.cpp \ + $$P/UI/GamepadEmu.cpp \ + $$P/UI/GameInfoCache.cpp \ + $$P/UI/OnScreenDisplay.cpp \ + $$P/UI/UIShader.cpp \ + $$P/UI/ui_atlas_lowmem.cpp \ + $$P/android/jni/TestRunner.cpp -HEADERS += ../UI/*.h -INCLUDEPATH += .. ../Common ../native +HEADERS += $$P/UI/*.h +INCLUDEPATH += $$P $$P/Common $$P/native $$P/native/ext # Use forms UI for desktop platforms !mobile_platform { - SOURCES += *.cpp - HEADERS += *.h - FORMS += *.ui - RESOURCES += resources.qrc - INCLUDEPATH += ../Qt + SOURCES += $$P/Qt/*.cpp + HEADERS += $$P/Qt/*.h + FORMS += $$P/Qt/*.ui + RESOURCES += $$P/Qt/desktop_assets.qrc + INCLUDEPATH += $$P/Qt # Translations - TRANSLATIONS = $$files(languages/ppsspp_*.ts) + TRANSLATIONS = $$files($$P/Qt/languages/ppsspp_*.ts) lang.name = lrelease ${QMAKE_FILE_IN} lang.input = TRANSLATIONS @@ -98,14 +110,8 @@ INCLUDEPATH += .. ../Common ../native PRE_TARGETDEPS += compiler_lang_make_all } else { # Desktop handles the Init separately - SOURCES += ../UI/NativeApp.cpp -} -symbian { - RESOURCES += assets_lowmem.qrc - SOURCES += ../UI/ui_atlas_lowmem.cpp -} else { - RESOURCES += assets.qrc - SOURCES += ../UI/ui_atlas.cpp + RESOURCES += $$P/Qt/assets.qrc + SOURCES += $$P/UI/NativeApp.cpp } # Packaging @@ -113,20 +119,9 @@ symbian { TARGET.UID3 = 0xE0095B1D DEPLOYMENT.display_name = PPSSPP vendor_deploy.pkg_prerules = "%{\"Qtness\"}" ":\"Qtness\"" - ICON = ../assets/icon.svg + ICON = $$P/assets/icon.svg - # Folders: - assets.sources = ../flash0 ../assets/langregion.ini - assets.path = E:/PPSSPP - shaders.sources = ../assets/shaders - shaders.path = E:/PPSSPP/PSP - lang.sources = $$files(../lang/*.ini) - # Unsupported languages on Symbian. Slashes differ depending on host. - contains(QMAKE_HOST.os, "Windows"): lang.sources -= ..\\lang/ja_JP.ini ..\\lang/ko_KR.ini ..\\lang/zh_CN.ini ..\\lang/zh_TW.ini - else: lang.sources -= ../lang/ja_JP.ini ../lang/ko_KR.ini ../lang/zh_CN.ini ../lang/zh_TW.ini - lang.path = E:/PPSSPP/lang - - DEPLOYMENT += vendor_deploy assets shaders lang + DEPLOYMENT += vendor_deploy # 268 MB maximum TARGET.EPOCHEAPSIZE = 0x40000 0x10000000 @@ -135,17 +130,11 @@ symbian { contains(MEEGO_EDITION,harmattan) { target.path = /opt/PPSSPP/bin - assets.files = ../flash0 ../assets/langregion.ini - assets.path = /opt/PPSSPP - shaders.files = ../assets/shaders - shaders.path = /opt/PPSSPP/PSP - lang.files = $$files(../lang/*.ini) - lang.path = /opt/PPSSPP/lang desktopfile.files = PPSSPP.desktop desktopfile.path = /usr/share/applications - icon.files = ../assets/icon-114.png + icon.files = $$P/assets/icon-114.png icon.path = /usr/share/icons/hicolor/114x114/apps - INSTALLS += target assets shaders lang desktopfile icon + INSTALLS += target desktopfile icon # Booster QMAKE_CXXFLAGS += -fPIC -fvisibility=hidden -fvisibility-inlines-hidden QMAKE_LFLAGS += -pie -rdynamic diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp index 55f270190d..74d5215490 100644 --- a/Qt/QtHost.cpp +++ b/Qt/QtHost.cpp @@ -1,15 +1,17 @@ -// This file is Qt's equivalent of NativeApp.cpp +// This file is Qt Desktop's equivalent of NativeApp.cpp #include #include #include #include +#include #include "QtHost.h" #include "LogManager.h" #include "Core/Debugger/SymbolMap.h" #include "Core/Config.h" #include "base/NativeApp.h" +#include "i18n/i18n.h" #include "UI/EmuScreen.h" #include "UI/UIShader.h" #include "UI/MiscScreens.h" @@ -18,8 +20,9 @@ #include "UI/ui_atlas.h" #include "ui/ui.h" #include "ui/ui_context.h" +#include "gfx_es2/draw_text.h" #include "GPU/ge_constants.h" -#include "EmuThread.h" +#include "ext/jpge/jpge.h" static UI::Theme ui_theme; @@ -40,6 +43,8 @@ static bool isMessagePending; static std::string pendingMessage; static std::string pendingValue; +bool g_TakeScreenshot; + QtHost::QtHost(MainWindow *mainWindow_) : mainWindow(mainWindow_) , m_GPUStep(false) @@ -66,7 +71,7 @@ void QtHost::SetWindowTitle(const char *message) void QtHost::UpdateUI() { - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); } @@ -97,7 +102,6 @@ void QtHost::SetDebugMode(bool mode) void QtHost::BeginFrame() { - mainWindow->Update(); } void QtHost::EndFrame() @@ -121,9 +125,9 @@ void QtHost::BootDone() } -static QString SymbolMapFilename(QString currentFilename) +static const char* SymbolMapFilename(std::string currentFilename) { - std::string result = currentFilename.toStdString(); + std::string result = currentFilename; size_t dot = result.rfind('.'); if (dot == result.npos) return (result + ".map").c_str(); @@ -134,17 +138,17 @@ static QString SymbolMapFilename(QString currentFilename) bool QtHost::AttemptLoadSymbolMap() { - return symbolMap.LoadSymbolMap(SymbolMapFilename(GetCurrentFilename()).toStdString().c_str()); + return symbolMap.LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); } void QtHost::PrepareShutdown() { - symbolMap.SaveSymbolMap(SymbolMapFilename(GetCurrentFilename()).toStdString().c_str()); + symbolMap.SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); } void QtHost::AddSymbol(std::string name, u32 addr, u32 size, int type=0) { - symbolMap.AddSymbol(name.c_str(), addr, size, (SymbolType)type); + } bool QtHost::IsDebuggingEnabled() @@ -179,7 +183,6 @@ void QtHost::GPUNotifyCommand(u32 pc) void QtHost::SendCoreWait(bool isWaiting) { - mainWindow->CoreEmitWait(isWaiting); } bool QtHost::GpuStep() @@ -189,20 +192,14 @@ bool QtHost::GpuStep() void QtHost::SendGPUStart() { - EmuThread_LockDraw(false); - if(m_GPUFlag == -1) { m_GPUFlag = 0; } - - EmuThread_LockDraw(true); } void QtHost::SendGPUWait(u32 cmd, u32 addr, void *data) { - EmuThread_LockDraw(false); - if((m_GPUFlag == 1 && (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE))) { // Break after the draw @@ -231,8 +228,6 @@ void QtHost::SendGPUWait(u32 cmd, u32 addr, void *data) m_hGPUStepEvent.wait(m_hGPUStepMutex); } } - - EmuThread_LockDraw(true); } void QtHost::SetGPUStep(bool value, int flag, u32 data) @@ -249,19 +244,29 @@ void QtHost::NextGPUStep() void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID) { - Common::EnableCrashingOnCrashes(); isMessagePending = false; std::string user_data_path = savegame_directory; +#ifdef Q_OS_LINUX + char* config = getenv("XDG_CONFIG_HOME"); + if (!config) { + config = getenv("HOME"); + strcat(config, "/.config"); + } + std::string memcard_path = std::string(config) + "/ppsspp/"; +#else std::string memcard_path = QDir::homePath().toStdString() + "/.ppsspp/"; +#endif VFSRegister("", new DirectoryAssetReader("assets/")); VFSRegister("", new DirectoryAssetReader(user_data_path.c_str())); + VFSRegister("", new AssetsAssetReader()); g_Config.AddSearchPath(user_data_path); g_Config.AddSearchPath(memcard_path + "PSP/SYSTEM/"); - g_Config.SetDefaultPath(g_Config.memCardDirectory + "PSP/SYSTEM/"); + g_Config.SetDefaultPath(memcard_path + "PSP/SYSTEM/"); g_Config.Load(); + i18nrepo.LoadIni(g_Config.sLanguageIni); const char *fileToLog = 0; @@ -313,9 +318,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co g_Config.currentDirectory = QDir::homePath().toStdString(); } - g_Config.memCardDirectory = QDir::homePath().toStdString() + "/.ppsspp/"; + g_Config.memCardDirectory = memcard_path; -#if defined(Q_OS_LINUX) && !defined(ARM) +#if defined(Q_OS_LINUX) std::string program_path = QCoreApplication::applicationDirPath().toStdString(); if (File::Exists(program_path + "/flash0")) g_Config.flash0Directory = program_path + "/flash0/"; @@ -333,11 +338,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co g_gameInfoCache.Init(); -#if !defined(ARM) // Start Desktop UI MainWindow* mainWindow = new MainWindow(); mainWindow->show(); -#endif } int NativeMix(short *audio, int num_samples) @@ -348,6 +351,57 @@ int NativeMix(short *audio, int num_samples) return 0; } +void TakeScreenshot() { + g_TakeScreenshot = false; + mkDir(g_Config.memCardDirectory + "/PSP/SCREENSHOT"); + + // First, find a free filename. + int i = 0; + + char temp[256]; + while (i < 10000){ + if(g_Config.bScreenshotsAsPNG) + sprintf(temp, "%s/PSP/SCREENSHOT/screen%05d.png", g_Config.memCardDirectory.c_str(), i); + else + sprintf(temp, "%s/PSP/SCREENSHOT/screen%05d.jpg", g_Config.memCardDirectory.c_str(), i); + FileInfo info; + if (!getFileInfo(temp, &info)) + break; + i++; + } + + // Okay, allocate a buffer. + u8 *buffer = new u8[3 * pixel_xres * pixel_yres]; + // Silly openGL reads upside down, we flip to another buffer for simplicity. + u8 *flipbuffer = new u8[3 * pixel_xres * pixel_yres]; + + glReadPixels(0, 0, pixel_xres, pixel_yres, GL_RGB, GL_UNSIGNED_BYTE, buffer); + + for (int y = 0; y < pixel_yres; y++) { + memcpy(flipbuffer + y * pixel_xres * 3, buffer + (pixel_yres - y - 1) * pixel_xres * 3, pixel_xres * 3); + } + + if (g_Config.bScreenshotsAsPNG) { + png_image png; + memset(&png, 0, sizeof(png)); + png.version = PNG_IMAGE_VERSION; + png.format = PNG_FORMAT_RGB; + png.width = pixel_xres; + png.height = pixel_yres; + png_image_write_to_file(&png, temp, 0, flipbuffer, pixel_xres * 3, NULL); + png_image_free(&png); + } else { + jpge::params params; + params.m_quality = 90; + compress_image_to_jpeg_file(temp, pixel_xres, pixel_yres, 3, flipbuffer, params); + } + + delete [] buffer; + delete [] flipbuffer; + + osm.Show(temp); +} + void NativeInitGraphics() { gl_lost_manager_init(); @@ -442,6 +496,12 @@ void NativeRender() glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); screenManager->render(); + if (screenManager->getUIContext()->Text()) { + screenManager->getUIContext()->Text()->OncePerFrame(); + } + + if (g_TakeScreenshot) + TakeScreenshot(); } void NativeMessageReceived(const char *message, const char *value) diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 25905f66ff..002d4b4a27 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -12,14 +12,12 @@ #include "gfx/texture.h" #include "input/input_state.h" #include "math/math_util.h" -#include "base/mutex.h" #include "math/lin/matrix4x4.h" #include // Globals static PMixer *g_mixer; static QString fileToStart; -static QtEmuGL* glWindow; class QtHost : public QObject, public Host { diff --git a/Qt/Settings.pri b/Qt/Settings.pri index ee7ffdfcdf..ed229e7738 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -1,5 +1,6 @@ +VERSION = 0.9.5 DEFINES += USING_QT_UI USE_FFMPEG -unix:!qnx:!symbian:!macx: CONFIG += linux +unix:!qnx:!symbian:!mac: CONFIG += linux # Global specific win32:CONFIG(release, debug|release): CONFIG_DIR = $$join(OUT_PWD,,,/release) @@ -8,18 +9,27 @@ else:CONFIG_DIR=$$OUT_PWD OBJECTS_DIR = $$CONFIG_DIR/.obj/$$TARGET MOC_DIR = $$CONFIG_DIR/.moc/$$TARGET UI_DIR = $$CONFIG_DIR/.ui/$$TARGET -INCLUDEPATH += ../ext/zlib ../native/ext/glew ../Common +P = $$_PRO_FILE_PWD_/.. +INCLUDEPATH += $$P/ext/zlib $$P/native/ext/glew $$P/Common + +exists($$P/.git): GIT_VERSION = '\\"$$system(git describe --always)\\"' +isEmpty(GIT_VERSION): GIT_VERSION = '\\"$$VERSION\\"' +DEFINES += PPSSPP_GIT_VERSION=\"$$GIT_VERSION\" win32-msvc* { QMAKE_CXXFLAGS_RELEASE += /O2 /arch:SSE2 /fp:fast DEFINES += _MBCS GLEW_STATIC _CRT_SECURE_NO_WARNINGS - PRECOMPILED_HEADER = ../Windows/stdafx.h - PRECOMPILED_SOURCE = ../Windows/stdafx.cpp - INCLUDEPATH += .. ../ffmpeg/Windows/$${QMAKE_TARGET.arch}/include + DEFINES += "_VARIADIC_MAX=10" + contains(DEFINES,UNICODE): DEFINES+=_UNICODE + PRECOMPILED_HEADER = $$P/Windows/stdafx.h + PRECOMPILED_SOURCE = $$P/Windows/stdafx.cpp + INCLUDEPATH += .. $$P/ffmpeg/Windows/$${QMAKE_TARGET.arch}/include } else { DEFINES += __STDC_CONSTANT_MACROS QMAKE_CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter - QMAKE_CXXFLAGS += -std=c++0x -ffast-math -fno-strict-aliasing + QMAKE_CXXFLAGS += -ffast-math -fno-strict-aliasing + contains(MEEGO_EDITION,harmattan): QMAKE_CXXFLAGS += -std=gnu++0x + else: QMAKE_CXXFLAGS += -std=c++0x QMAKE_CFLAGS_RELEASE -= -O2 QMAKE_CFLAGS_RELEASE += -O3 QMAKE_CXXFLAGS_RELEASE -= -O2 @@ -50,23 +60,31 @@ contains(MEEGO_EDITION,harmattan) { DEFINES += MEEGO_EDITION_HARMATTAN "_SYS_UCONTEXT_H=1" } +macx { + INCLUDEPATH += $$P/ffmpeg/macosx/x86_64/include + #the qlist headers include in QT5 + greaterThan(QT_MAJOR_VERSION,4):CONFIG+=c++11 +} + +ios { + INCLUDEPATH += $$P/ffmpeg/ios/universal/include +} + linux:!mobile_platform { contains(QT_ARCH, x86_64): QMAKE_TARGET.arch = x86_64 else: QMAKE_TARGET.arch = x86 - INCLUDEPATH += ../ffmpeg/linux/$${QMAKE_TARGET.arch}/include + INCLUDEPATH += $$P/ffmpeg/linux/$${QMAKE_TARGET.arch}/include } -linux:mobile_platform: INCLUDEPATH += ../ffmpeg/linux/arm/include +linux:mobile_platform: INCLUDEPATH += $$P/ffmpeg/linux/arm/include qnx { # Use mkspec: unsupported/qws/qnx-armv7-g++ DEFINES += BLACKBERRY "_QNX_SOURCE=1" "_C99=1" - INCLUDEPATH += ../ffmpeg/blackberry/armv7/include + INCLUDEPATH += $$P/ffmpeg/blackberry/armv7/include } symbian { # Does not seem to be a way to change to armv6 compile so just override in variants.xml (see README) - MMP_RULES -= "ARMFPU softvfp+vfpv2" - MMP_RULES += "ARMFPU vfpv2" -#"BOOST_COMPILER_CONFIG=" + DEFINES += "BOOST_COMPILER_CONFIG=\"$$EPOCROOT/epoc32/include/stdapis/boost/mpl/aux_/config/gcc.hpp\"" QMAKE_CXXFLAGS += -marm -Wno-parentheses -Wno-comment - INCLUDEPATH += $$EPOCROOT/epoc32/include/stdapis $$EPOCROOT/epoc32/include/stdapis/glib-2.0 - INCLUDEPATH += ../ffmpeg/symbian/armv6/include + INCLUDEPATH += $$EPOCROOT/epoc32/include/stdapis + INCLUDEPATH += $$P/ffmpeg/symbian/armv6/include } diff --git a/Qt/assets.qrc b/Qt/assets.qrc index 921c087e92..103d6c1c0b 100644 --- a/Qt/assets.qrc +++ b/Qt/assets.qrc @@ -1,6 +1,13 @@ - - ../assets/ui_atlas.zim - ../assets/ppge_atlas.zim - + + ../assets/ui_atlas_lowmem.zim + ../assets/ppge_atlas.zim + ../lang + ../assets/langregion.ini + ../assets/unknown.png + ../assets/shaders + ../flash0/font + ../assets/rargray.png + ../assets/zip.png + diff --git a/Qt/assets_lowmem.qrc b/Qt/assets_lowmem.qrc deleted file mode 100644 index 2306ce6b4e..0000000000 --- a/Qt/assets_lowmem.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - ../assets/ui_atlas_lowmem.zim - ../assets/ppge_atlas.zim - - diff --git a/Qt/controls.cpp b/Qt/controls.cpp deleted file mode 100644 index b029300ef3..0000000000 --- a/Qt/controls.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "controls.h" -#include "ui_controls.h" -#include "Core/Config.h" -#include "EmuThread.h" -#include - -Controls_ controllist[] = { - {"Edit_Start", "Start", Qt::Key_1, PAD_BUTTON_START, CTRL_START}, - {"Edit_Select", "Select", Qt::Key_2, PAD_BUTTON_SELECT, CTRL_SELECT}, - {"Edit_S", "Square", Qt::Key_Z, PAD_BUTTON_X, CTRL_SQUARE}, - {"Edit_T", "Triangle", Qt::Key_A, PAD_BUTTON_Y, CTRL_TRIANGLE}, - {"Edit_O", "Circle", Qt::Key_S, PAD_BUTTON_B, CTRL_CIRCLE}, - {"Edit_X", "Cross", Qt::Key_X, PAD_BUTTON_A, CTRL_CROSS}, - {"Edit_LT", "Left Trigger", Qt::Key_Q, PAD_BUTTON_LBUMPER, CTRL_LTRIGGER}, - {"Edit_RT", "Right Trigger", Qt::Key_W, PAD_BUTTON_RBUMPER, CTRL_RTRIGGER}, - {"Edit_Up", "Up", Qt::Key_Up, PAD_BUTTON_UP, CTRL_UP}, - {"Edit_Down", "Down", Qt::Key_Down, PAD_BUTTON_DOWN, CTRL_DOWN}, - {"Edit_Left", "Left", Qt::Key_Left, PAD_BUTTON_LEFT, CTRL_LEFT}, - {"Edit_Right", "Right", Qt::Key_Right, PAD_BUTTON_RIGHT, CTRL_RIGHT}, - {"", "Analog Up", Qt::Key_I, PAD_BUTTON_JOY_UP, 0}, - {"", "Analog Down", Qt::Key_K, PAD_BUTTON_JOY_DOWN,0}, - {"", "Analog Left", Qt::Key_J, PAD_BUTTON_JOY_LEFT,0}, - {"", "Analog Right", Qt::Key_L, PAD_BUTTON_JOY_RIGHT,0}, -}; - -Controls::Controls(QWidget *parent) : - QDialog(parent), - ui(new Ui::Controls) -{ - ui->setupUi(this); - - /*for(int i = 0; i < controllistCount; i++) - { - if(g_Config.iMappingMap.find(i) != g_Config.iMappingMap.end()) - { - controllist[i].key = (Qt::Key)g_Config.iMappingMap[i]; - } - }*/ -} - -Controls::~Controls() -{ - delete ui; -} - -void Controls::showEvent(QShowEvent*) -{ -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif -/* - for(int i = 0; i < controllistCount; i++) - { - if(g_Config.iMappingMap.find(i) != g_Config.iMappingMap.end()) - { - controllist[i].key = (Qt::Key)g_Config.iMappingMap[i]; - } - - if(controllist[i].editName != "") - { - QLineEdit* edit = findChild(controllist[i].editName); - if(edit) - { - QKeySequence sec(controllist[i].key); - edit->setText(sec.toString()); - } - } - }*/ -} - -void Controls::changeEvent(QEvent *event) -{ - if (event) - if (event->type() == QEvent::LanguageChange) - ui->retranslateUi(this); - - QDialog::changeEvent(event); -} - -void Controls::releaseLock() -{ - EmuThread_LockDraw(false); -} - -void Controls::on_buttonBox_accepted() -{ -/* - for(int i = 0; i < controllistCount; i++) - { - if(controllist[i].editName != "") - { - QLineEdit* edit = findChild(controllist[i].editName); - if(edit) - { - QKeySequence sec(edit->text()); - controllist[i].key = (Qt::Key)sec[0]; - g_Config.iMappingMap[i] = sec[0]; - } - } - }*/ -} diff --git a/Qt/controls.h b/Qt/controls.h deleted file mode 100644 index 4a319874a6..0000000000 --- a/Qt/controls.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef CONTROLS_H -#define CONTROLS_H - -#include -#include "native/input/input_state.h" -#include "Core/HLE/sceCtrl.h" - -namespace Ui { -class Controls; -} - -struct Controls_ -{ -public: - QString editName; - QString command; - Qt::Key key; - int emu_id; - int psp_id; -}; - -const int controllistCount = 16; -extern Controls_ controllist[]; - -class Controls : public QDialog -{ - Q_OBJECT - -public: - explicit Controls(QWidget *parent = 0); - ~Controls(); - - void showEvent(QShowEvent *); - void changeEvent(QEvent *); -private slots: - void releaseLock(); - void on_buttonBox_accepted(); - -private: - Ui::Controls *ui; -}; - -#endif // CONTROLS_H diff --git a/Qt/controls.ui b/Qt/controls.ui deleted file mode 100644 index d129dd05c7..0000000000 --- a/Qt/controls.ui +++ /dev/null @@ -1,272 +0,0 @@ - - - Controls - - - - 0 - 0 - 618 - 357 - - - - - 0 - 0 - - - - Controls - - - - - - - 600 - 300 - - - - - 600 - 300 - - - - - - 50 - 50 - 501 - 191 - - - - - - - :/images/resources/psp.png - - - - - - 50 - 100 - 41 - 25 - - - - - - - 30 - 130 - 41 - 25 - - - - - - - 80 - 130 - 41 - 25 - - - - - - - 50 - 160 - 41 - 25 - - - - - - - 150 - 240 - 41 - 25 - - - - - - - 410 - 240 - 41 - 25 - - - - - - - 360 - 240 - 41 - 25 - - - - - - - 510 - 160 - 41 - 25 - - - - - - - 480 - 130 - 41 - 25 - - - - - - - 530 - 130 - 41 - 25 - - - - - - - 510 - 100 - 41 - 25 - - - - - - - 440 - 20 - 41 - 25 - - - - - - - 120 - 20 - 41 - 25 - - - - - - - 50 - 50 - 501 - 191 - - - - - - - :/images/resources/psp_map.png - - - PSP_Img - PSP_Img_2 - Edit_Up - Edit_Left - Edit_Right - Edit_Down - Edit_Home - Edit_Start - Edit_Select - Edit_X - Edit_S - Edit_O - Edit_T - Edit_RT - Edit_LT - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - QKeyEdit - QLineEdit -
qkeyedit.h
-
-
- - - - - - buttonBox - accepted() - Controls - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Controls - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
diff --git a/Qt/ctrldisasmview.cpp b/Qt/ctrldisasmview.cpp index 3bf021f23e..03e73d5cc6 100644 --- a/Qt/ctrldisasmview.cpp +++ b/Qt/ctrldisasmview.cpp @@ -8,6 +8,8 @@ #include #include +#include "math.h" + #include "debugger_disasm.h" #include "Core/Debugger/SymbolMap.h" @@ -60,9 +62,7 @@ void CtrlDisAsmView::mousePressEvent(QMouseEvent *e) } else { - EmuThread_LockDraw(true); debugger->toggleBreakpoint(yToAddress(y)); - EmuThread_LockDraw(false); parentWindow->Update(); redraw(); } @@ -154,40 +154,30 @@ void CtrlDisAsmView::CopyAddress() void CtrlDisAsmView::CopyInstrDisAsm() { - EmuThread_LockDraw(true); QApplication::clipboard()->setText(debugger->disasm(selection,align)); - EmuThread_LockDraw(false); } void CtrlDisAsmView::CopyInstrHex() { - EmuThread_LockDraw(true); QApplication::clipboard()->setText(QString("%1").arg(debugger->readMemory(selection),8,16,QChar('0'))); - EmuThread_LockDraw(false); } void CtrlDisAsmView::SetNextStatement() { - EmuThread_LockDraw(true); debugger->setPC(selection); - EmuThread_LockDraw(false); redraw(); } void CtrlDisAsmView::ToggleBreakpoint() { - EmuThread_LockDraw(true); debugger->toggleBreakpoint(selection); - EmuThread_LockDraw(false); parentWindow->Update(); redraw(); } void CtrlDisAsmView::FollowBranch() { - EmuThread_LockDraw(true); - const char *temp = debugger->disasm(selection,align); - EmuThread_LockDraw(false); + const char *temp = debugger->disasm(selection,align);; const char *mojs=strstr(temp,"->$"); if (mojs) { @@ -203,29 +193,27 @@ void CtrlDisAsmView::FollowBranch() void CtrlDisAsmView::RunToHere() { - EmuThread_LockDraw(true); debugger->setBreakpoint(selection); debugger->runToBreakpoint(); - EmuThread_LockDraw(false); redraw(); } void CtrlDisAsmView::RenameFunction() { - int sym = symbolMap.GetSymbolNum(selection); - if (sym != -1) - { - QString name = symbolMap.GetSymbolName(sym); - bool ok; - QString newname = QInputDialog::getText(this, tr("New function name"), - tr("New function name:"), QLineEdit::Normal, - name, &ok); - if (ok && !newname.isEmpty()) - { - symbolMap.SetSymbolName(sym,newname.toStdString().c_str()); - redraw(); - parentWindow->NotifyMapLoaded(); - } + u32 funcBegin = symbolMap.GetFunctionStart(curAddress); + if (funcBegin != -1) + { + QString name = symbolMap.GetLabelName(funcBegin); + bool ok; + QString newname = QInputDialog::getText(this, tr("New function name"), + tr("New function name:"), QLineEdit::Normal, + name, &ok); + if (ok && !newname.isEmpty()) + { + symbolMap.SetLabelName(newname.toStdString().c_str(),funcBegin); + redraw(); + parentWindow->NotifyMapLoaded(); + } } else { @@ -249,7 +237,7 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) int numBranches=0; int width = rect().width(); - int numRows=(rect().height()/rowHeight)/2+1; + int numRows=(rect().height()/rowHeight); QColor bgColor(0xFFFFFFFF); QPen nullPen(bgColor); @@ -265,34 +253,39 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) QFont normalFont("Arial", 10); QFont boldFont("Arial", 10); QFont alignedFont("Monospace", 10); + alignedFont.setStyleHint(QFont::Monospace); boldFont.setBold(true); painter.setFont(normalFont); - QImage breakPoint(":/images/breakpoint"); + QImage breakPoint(":/resources/breakpoint.ico"); int i; curAddress&=~(align-1); align=(debugger->getInstructionSize(0)); - for (i=-numRows; i<=numRows; i++) + for (i=0; i<=numRows; i++) { - unsigned int address=curAddress + i*align; + unsigned int address=curAddress + (i-(numRows/2))*align; - int rowY1 = rect().bottom()/2 + rowHeight*i - rowHeight/2; - int rowY2 = rect().bottom()/2 + rowHeight*i + rowHeight/2 - 1; + int rowY1 = rect().top() + rowHeight*i; + int rowY2 = rect().top() + rowHeight*i + rowHeight - 1; lbr.setColor((unsigned int)marker == address ? QColor(0xFFFFEEE0) : QColor(debugger->getColor(address))); QColor bg = lbr.color(); + painter.setBrush(currentBrush); painter.setPen(nullPen); painter.drawRect(0,rowY1,16-1,rowY2-rowY1); if (selecting && address == (unsigned int)selection) painter.setPen(selPen); else - painter.setPen(i==0 ? currentPen : nullPen); - - QBrush mojsBrush(lbr.color()); - painter.setBrush(mojsBrush); + { + if(i==numRows/2) + painter.setPen(currentPen); + else + painter.setPen(bg); + } + painter.setBrush(QBrush(bg)); if (address == debugger->getPC()) { @@ -422,7 +415,8 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) int CtrlDisAsmView::yToAddress(int y) { - int ydiff=y-rect().bottom()/2-rowHeight/2; - ydiff=(int)(floor((float)ydiff / (float)rowHeight))+1; - return curAddress + ydiff * align; + //int ydiff=y - rect().bottom()/2;//-rowHeight/2; + int ydiff=(int)(floor((float)y / (float)rowHeight)); + ydiff -= (rect().height()/rowHeight)/2; + return curAddress + ydiff *align; } diff --git a/Qt/ctrldisasmview.h b/Qt/ctrldisasmview.h index d60be7ac77..8846ad40db 100644 --- a/Qt/ctrldisasmview.h +++ b/Qt/ctrldisasmview.h @@ -3,7 +3,6 @@ #include #include "Core/Debugger/DebugInterface.h" -#include "EmuThread.h" class Debugger_Disasm; @@ -26,11 +25,9 @@ public: void setDebugger(DebugInterface *deb) { - EmuThread_LockDraw(true); debugger=deb; curAddress=debugger->getPC(); align=debugger->getInstructionSize(0); - EmuThread_LockDraw(false); } DebugInterface *getDebugger() { @@ -43,9 +40,7 @@ public: } void gotoPC() { - EmuThread_LockDraw(true); curAddress=debugger->getPC()&(~(align-1)); - EmuThread_LockDraw(false); redraw(); } unsigned int getSelection() @@ -60,9 +55,7 @@ public: void toggleBreakpoint() { - EmuThread_LockDraw(true); debugger->toggleBreakpoint(curAddress); - EmuThread_LockDraw(false); redraw(); } diff --git a/Qt/ctrlmemview.cpp b/Qt/ctrlmemview.cpp index ddd05047e2..3316169667 100644 --- a/Qt/ctrlmemview.cpp +++ b/Qt/ctrlmemview.cpp @@ -8,7 +8,8 @@ #include #include -#include "EmuThread.h" +#include "math.h" + #include "Core/MemMap.h" #include "Core/Debugger/SymbolMap.h" @@ -82,7 +83,7 @@ void CtrlMemView::paintEvent(QPaintEvent *) QFont normalFont("Arial", 10); QFont alignedFont("Monospace", 10); - alignedFont.setStyleHint(QFont::Monospace); + alignedFont.setStyleHint(QFont::Monospace); painter.setFont(normalFont); int i; @@ -121,14 +122,12 @@ void CtrlMemView::paintEvent(QPaintEvent *) const char *m = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; if (Memory::IsValidAddress(address)) { - EmuThread_LockDraw(true); u32 memory[4] = { debugger->readMemory(address), debugger->readMemory(address+4), debugger->readMemory(address+8), debugger->readMemory(address+12) }; - EmuThread_LockDraw(false); m = (const char*)memory; sprintf(temp, "%08x %08x %08x %08x ................", memory[0],memory[1],memory[2],memory[3]); @@ -146,7 +145,7 @@ void CtrlMemView::paintEvent(QPaintEvent *) case MV_SYMBOLS: { - textPen.setColor(0x0000FF); +/* textPen.setColor(0x0000FF); painter.setPen(textPen); int fn = symbolMap.GetSymbolNum(address); if (fn==-1) @@ -175,7 +174,7 @@ void CtrlMemView::paintEvent(QPaintEvent *) sprintf(temp, "%04x [%s]", value, symbolMap.GetSymbolName(symbolnum)); } - painter.drawText(85,rowY1 - 2 + rowHeight, temp); + painter.drawText(85,rowY1 - 2 + rowHeight, temp);*/ break; } case MV_MAX: break; @@ -226,9 +225,7 @@ void CtrlMemView::contextMenu(const QPoint &pos) void CtrlMemView::CopyValue() { - EmuThread_LockDraw(true); QApplication::clipboard()->setText(QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0'))); - EmuThread_LockDraw(false); } void CtrlMemView::Dump() @@ -239,9 +236,7 @@ void CtrlMemView::Dump() void CtrlMemView::Change() { - EmuThread_LockDraw(true); QString curVal = QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0')); - EmuThread_LockDraw(false); bool ok; QString text = QInputDialog::getText(this, tr("Set new value"), @@ -249,9 +244,7 @@ void CtrlMemView::Change() curVal, &ok); if (ok && !text.isEmpty()) { - EmuThread_LockDraw(true); Memory::WriteUnchecked_U32(text.toUInt(0,16),selection); - EmuThread_LockDraw(false); redraw(); } } diff --git a/Qt/ctrlregisterlist.cpp b/Qt/ctrlregisterlist.cpp index 4179d775e8..29184ee1ab 100644 --- a/Qt/ctrlregisterlist.cpp +++ b/Qt/ctrlregisterlist.cpp @@ -7,7 +7,6 @@ #include #include #include -#include "EmuThread.h" #include "debugger_disasm.h" CtrlRegisterList::CtrlRegisterList(QWidget *parent) : @@ -286,9 +285,7 @@ void CtrlRegisterList::GotoMemory() if (selection >= cpu->GetNumRegsInCategory(cat)) return; - EmuThread_LockDraw(true); u32 val = cpu->GetRegValue(cat,reg); - EmuThread_LockDraw(false); parentWindow->ShowMemory(val); } @@ -300,9 +297,7 @@ void CtrlRegisterList::GotoDisAsm() if (selection >= cpu->GetNumRegsInCategory(cat)) return; - EmuThread_LockDraw(true); u32 val = cpu->GetRegValue(cat,reg); - EmuThread_LockDraw(false); emit GotoDisasm(val); } @@ -314,9 +309,7 @@ void CtrlRegisterList::CopyValue() if (selection >= cpu->GetNumRegsInCategory(cat)) return; - EmuThread_LockDraw(true); u32 val = cpu->GetRegValue(cat,reg); - EmuThread_LockDraw(false); QApplication::clipboard()->setText(QString("%1").arg(val,8,16,QChar('0'))); } @@ -328,9 +321,7 @@ void CtrlRegisterList::Change() if (selection >= cpu->GetNumRegsInCategory(cat)) return; - EmuThread_LockDraw(true); u32 val = cpu->GetRegValue(cat,reg); - EmuThread_LockDraw(false); bool ok; QString text = QInputDialog::getText(this, tr("Set new value"), @@ -338,9 +329,7 @@ void CtrlRegisterList::Change() QString::number(val), &ok); if (ok && !text.isEmpty()) { - EmuThread_LockDraw(true); cpu->SetRegValue(cat,reg,text.toInt()); - EmuThread_LockDraw(false); redraw(); } } diff --git a/Qt/debugger_disasm.cpp b/Qt/debugger_disasm.cpp index c7cf4a7a6e..121cbf6afd 100644 --- a/Qt/debugger_disasm.cpp +++ b/Qt/debugger_disasm.cpp @@ -20,7 +20,6 @@ #include "GPU/GPUInterface.h" #include "GPU/GeDisasm.h" #include "GPU/Common/GPUDebugInterface.h" -#include "EmuThread.h" #include "Core/Host.h" Debugger_Disasm::Debugger_Disasm(DebugInterface *_cpu, MainWindow* mainWindow_, QWidget *parent) : @@ -37,7 +36,8 @@ Debugger_Disasm::Debugger_Disasm(DebugInterface *_cpu, MainWindow* mainWindow_, QObject::connect(ui->RegListScroll,SIGNAL(actionTriggered(int)), ui->RegList, SLOT(scrollChanged(int))); QObject::connect(ui->RegList,SIGNAL(GotoDisasm(u32)),this,SLOT(Goto(u32))); - QObject::connect(this, SIGNAL(updateDisplayList_()), this, SLOT(UpdateDisplayListGUI())); + QObject::connect(this, SIGNAL(UpdateCallstack_()), this, SLOT(UpdateCallstackGUI())); + QObject::connect(this, SIGNAL(UpdateDisplayList_()), this, SLOT(UpdateDisplayListGUI())); QObject::connect(this, SIGNAL(UpdateBreakpoints_()), this, SLOT(UpdateBreakpointsGUI())); QObject::connect(this, SIGNAL(UpdateThread_()), this, SLOT(UpdateThreadGUI())); @@ -54,27 +54,6 @@ Debugger_Disasm::Debugger_Disasm(DebugInterface *_cpu, MainWindow* mainWindow_, } -void Debugger_Disasm::showEvent(QShowEvent *) -{ - -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif - - if(Core_IsStepping()) - SetDebugMode(true); - else - SetDebugMode(false); -} - -void Debugger_Disasm::releaseLock() -{ - EmuThread_LockDraw(false); -} - - Debugger_Disasm::~Debugger_Disasm() { delete ui; @@ -88,47 +67,39 @@ void Debugger_Disasm::ShowVFPU() void Debugger_Disasm::Update() { ui->RegList->redraw(); - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); UpdateDialog(); } void Debugger_Disasm::Go() { SetDebugMode(false); - EmuThread_LockDraw(true); Core_EnableStepping(false); - EmuThread_LockDraw(false); - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); } void Debugger_Disasm::Step() { - EmuThread_LockDraw(true); Core_DoSingleStep(); - EmuThread_LockDraw(false); _dbg_update_(); } void Debugger_Disasm::StepOver() { SetDebugMode(false); - EmuThread_LockDraw(true); CBreakPoints::AddBreakPoint(cpu->GetPC()+cpu->getInstructionSize(0),true); _dbg_update_(); Core_EnableStepping(false); - EmuThread_LockDraw(false); - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); } void Debugger_Disasm::StepHLE() { - EmuThread_LockDraw(true); hleDebugBreak(); SetDebugMode(false); _dbg_update_(); Core_EnableStepping(false); - EmuThread_LockDraw(false); - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); } void Debugger_Disasm::UpdateDialog() @@ -142,34 +113,12 @@ void Debugger_Disasm::UpdateDialog() UpdateBreakpoints(); UpdateThread(); UpdateDisplayList(); + UpdateCallstack(); char tempTicks[24]; sprintf(tempTicks, "%lld", CoreTiming::GetTicks()); ui->debugCount->setText(QString("Ctr : ") + tempTicks); - /*ui->callStack->clear(); - u32 pc = currentMIPS->pc; - u32 ra = currentMIPS->r[MIPS_REG_RA]; - u32 addr = Memory::ReadUnchecked_U32(pc); - int count=1; - char addr_[12]; - sprintf(addr_, "0x%08x",pc); - ui->callStack->addItem(new QListWidgetItem(addr_)); - - addr = Memory::ReadUnchecked_U32(ra); - sprintf(addr_, "0x%08x",ra); - ui->callStack->addItem(new QListWidgetItem(addr_)); - count++; - - while (addr != 0xFFFFFFFF && addr!=0 && Memory::IsValidAddress(addr+4) && count++<20) - { - u32 fun = Memory::ReadUnchecked_U32(addr+4); - sprintf(addr_, "0x%08x",fun); - ui->callStack->addItem(new QListWidgetItem(addr_)); - addr = Memory::ReadUnchecked_U32(addr); - }*/ - - if(mainWindow->GetDialogMemory()) mainWindow->GetDialogMemory()->Update(); @@ -178,11 +127,9 @@ void Debugger_Disasm::UpdateDialog() void Debugger_Disasm::Stop() { SetDebugMode(true); - EmuThread_LockDraw(true); Core_EnableStepping(true); - EmuThread_LockDraw(false); _dbg_update_(); - mainWindow->UpdateMenus(); + mainWindow->updateMenus(); UpdateDialog(); } @@ -190,9 +137,7 @@ void Debugger_Disasm::Skip() { CtrlDisAsmView *ptr = ui->DisasmView; - EmuThread_LockDraw(true); cpu->SetPC(cpu->GetPC() + cpu->getInstructionSize(0)); - EmuThread_LockDraw(false); ptr->gotoPC(); UpdateDialog(); } @@ -342,16 +287,61 @@ void Debugger_Disasm::FillFunctions() item->setData(Qt::UserRole, 0x02000000); ui->FuncList->addItem(item); - for(int i = 0; i < symbolMap.GetNumSymbols(); i++) + std::vector symbols = symbolMap.GetAllSymbols(ST_FUNCTION); + for(int i = 0; i < (int)symbols.size(); i++) + { + QListWidgetItem* item = new QListWidgetItem(); + item->setText(QString("%1 (%2)").arg(QString::fromStdString(symbols[i].name)).arg(symbols[i].size)); + item->setData(Qt::UserRole, symbols[i].address); + ui->FuncList->addItem(item); + } +} + +void Debugger_Disasm::UpdateCallstack() +{ + emit UpdateCallstack_(); +} + +void Debugger_Disasm::UpdateCallstackGUI() +{ + + auto threads = GetThreadsInfo(); + + u32 entry = 0, stackTop = 0; + for (size_t i = 0; i < threads.size(); i++) { - if(symbolMap.GetSymbolType(i) & ST_FUNCTION) + if (threads[i].isCurrent) { - QListWidgetItem* item = new QListWidgetItem(); - item->setText(QString("%1 (%2)").arg(symbolMap.GetSymbolName(i)).arg(symbolMap.GetSymbolSize(i))); - item->setData(Qt::UserRole, symbolMap.GetAddress(i)); - ui->FuncList->addItem(item); + entry = threads[i].entrypoint; + stackTop = threads[i].initialStack; + break; } } + if (entry != 0) { + stackTraceModel = MIPSStackWalk::Walk( + cpu->GetPC(), + cpu->GetRegValue(0,MIPS_REG_RA), + cpu->GetRegValue(0,MIPS_REG_SP), + entry, + stackTop); + } else { + stackTraceModel.clear(); + } + + ui->callStack->clear(); + + QTreeWidgetItem* item; + for(auto it=stackTraceModel.begin();it!=stackTraceModel.end();it++) + { + item = new QTreeWidgetItem(); + item->setText(0,QString("%1").arg(it->pc,8,16,QChar('0')).prepend("0x")); + item->setData(0,Qt::UserRole,it->pc); + item->setText(1,QString("%1").arg(it->entry,8,16,QChar('0')).prepend("0x")); + item->setData(1,Qt::UserRole,it->entry); + item->setText(2,QString("%1").arg(it->sp,8,16,QChar('0')).prepend("0x")); + item->setText(3,QString("%1").arg(it->stackSize,8,16,QChar('0')).prepend("0x")); + ui->callStack->addTopLevelItem(item); + } } void Debugger_Disasm::UpdateBreakpoints() @@ -368,7 +358,6 @@ void Debugger_Disasm::UpdateBreakpointsGUI() ui->breakpointsList->clear(); - EmuThread_LockDraw(true); auto breakpoints = CBreakPoints::GetBreakpoints(); for(size_t i = 0; i < breakpoints.size(); i++) { @@ -383,7 +372,6 @@ void Debugger_Disasm::UpdateBreakpointsGUI() ui->breakpointsList->setCurrentItem(item); } } - EmuThread_LockDraw(false); } void Debugger_Disasm::on_breakpointsList_itemClicked(QTreeWidgetItem *item, int column) @@ -429,9 +417,7 @@ void Debugger_Disasm::UpdateThreadGUI() { ui->threadList->clear(); - EmuThread_LockDraw(true); std::vector threads = GetThreadsInfo(); - EmuThread_LockDraw(false); for(size_t i = 0; i < threads.size(); i++) { @@ -508,9 +494,7 @@ void Debugger_Disasm::GotoThreadEntryPoint() void Debugger_Disasm::SetThreadStatus(ThreadStatus status) { - EmuThread_LockDraw(true); __KernelChangeThreadState(threadRowSelected->data(0,Qt::UserRole).toInt(), status); - EmuThread_LockDraw(false); UpdateThread(); } @@ -532,7 +516,7 @@ void Debugger_Disasm::SetThreadStatusSuspend() void Debugger_Disasm::UpdateDisplayList() { - emit updateDisplayList_(); + emit UpdateDisplayList_(); } void Debugger_Disasm::UpdateDisplayListGUI() @@ -544,7 +528,6 @@ void Debugger_Disasm::UpdateDisplayListGUI() ui->displayList->clear(); - EmuThread_LockDraw(true); const std::list& dlQueue = gpu->GetDisplayLists(); DisplayList dlist; @@ -605,7 +588,6 @@ void Debugger_Disasm::UpdateDisplayListGUI() } for(int i = 0; i < ui->displayList->columnCount(); i++) ui->displayList->resizeColumnToContents(i); - EmuThread_LockDraw(false); } void Debugger_Disasm::on_displayList_customContextMenuRequested(const QPoint &pos) diff --git a/Qt/debugger_disasm.h b/Qt/debugger_disasm.h index 4788b42fbf..aa06dc5bc8 100644 --- a/Qt/debugger_disasm.h +++ b/Qt/debugger_disasm.h @@ -1,12 +1,14 @@ #ifndef DEBUGGER_DISASM_H #define DEBUGGER_DISASM_H +#include "Core/MIPS/MIPSStackWalk.h" #include "Core/HLE/sceKernelThread.h" #include "Core/Debugger/DebugInterface.h" #include "debugger_vfpu.h" #include #include #include +#include class MainWindow; namespace Ui { @@ -36,14 +38,14 @@ public: void Update(); void ShowMemory(u32 addr); void FillFunctions(); + void UpdateCallstack(); void UpdateBreakpoints(); void UpdateThread(); void UpdateDisplayList(); -protected: - void showEvent(QShowEvent *); signals: - void updateDisplayList_(); + void UpdateCallstack_(); + void UpdateDisplayList_(); void UpdateBreakpoints_(); void UpdateThread_(); @@ -53,6 +55,7 @@ public slots: void GotoThreadEntryPoint(); private slots: + void UpdateCallstackGUI(); void UpdateDisplayListGUI(); void UpdateBreakpointsGUI(); void UpdateThreadGUI(); @@ -82,7 +85,6 @@ private slots: void SetThreadStatusWait(); void SetThreadStatusSuspend(); void on_displayList_customContextMenuRequested(const QPoint &pos); - void releaseLock(); private: void SetThreadStatus(ThreadStatus status); @@ -94,6 +96,7 @@ private: u32 breakpointAddr; QTreeWidgetItem* threadRowSelected; QTreeWidgetItem* displayListRowSelected; + std::vector stackTraceModel; }; #endif // DEBUGGER_DISASM_H diff --git a/Qt/debugger_disasm.ui b/Qt/debugger_disasm.ui index 0cc8967bcf..fb3b7e6e17 100644 --- a/Qt/debugger_disasm.ui +++ b/Qt/debugger_disasm.ui @@ -175,7 +175,7 @@ - 229 + 120 20 @@ -315,7 +315,7 @@ 0 - + Breakpoints @@ -367,17 +367,41 @@ - + Callstack - + + + 4 + + + + Address + + + + + Entry Point + + + + + SP + + + + + length + + + - + Display Lists @@ -428,7 +452,7 @@ - + Threads diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp index ebffa64cac..4f4ed76811 100644 --- a/Qt/debugger_displaylist.cpp +++ b/Qt/debugger_displaylist.cpp @@ -8,7 +8,6 @@ #include "ui_debugger_displaylist.h" #include "GPU/GPUInterface.h" #include "GPU/GeDisasm.h" -#include "EmuThread.h" #include "Core/Host.h" #include "base/display.h" #include "mainwindow.h" @@ -41,24 +40,6 @@ Debugger_DisplayList::~Debugger_DisplayList() delete ui; } - -void Debugger_DisplayList::showEvent(QShowEvent *) -{ - -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif - -} - -void Debugger_DisplayList::releaseLock() -{ - EmuThread_LockDraw(false); -} - - void Debugger_DisplayList::UpdateDisplayList() { emit updateDisplayList_(); @@ -76,7 +57,6 @@ void Debugger_DisplayList::UpdateDisplayListGUI() ui->displayList->clear(); ui->displayListData->clear(); - EmuThread_LockDraw(true); const std::list& dlQueue = gpu->GetDisplayLists(); for(auto listIdIt = dlQueue.begin(); listIdIt != dlQueue.end(); ++listIdIt) @@ -115,8 +95,6 @@ void Debugger_DisplayList::UpdateDisplayListGUI() displayListRowSelected = ui->displayList->topLevelItem(0); ShowDLCode(); } - - EmuThread_LockDraw(false); } @@ -1486,8 +1464,6 @@ void Debugger_DisplayList::UpdateRenderBuffer() void Debugger_DisplayList::UpdateRenderBufferGUI() { - EmuThread_LockDraw(true); - //gpu->Flush(); int FRAME_WIDTH; @@ -1534,8 +1510,6 @@ void Debugger_DisplayList::UpdateRenderBufferGUI() ui->fboImg->setMaximumHeight(pixmap.height() * fboZoomFactor); delete[] data; - - EmuThread_LockDraw(false); } void Debugger_DisplayList::on_nextDrawBtn_clicked() diff --git a/Qt/debugger_displaylist.h b/Qt/debugger_displaylist.h index 78b19d86b4..f2ccf6b2cd 100644 --- a/Qt/debugger_displaylist.h +++ b/Qt/debugger_displaylist.h @@ -48,8 +48,6 @@ public: void UpdateRenderBufferList(); void UpdateVertexInfo(); void UpdateIndexInfo(); -protected: - void showEvent(QShowEvent *); signals: void updateDisplayList_(); @@ -60,7 +58,6 @@ private slots: void UpdateDisplayListGUI(); void UpdateRenderBufferListGUI(); void UpdateRenderBufferGUI(); - void releaseLock(); void on_displayList_itemClicked(QTreeWidgetItem *item, int column); void on_stepBtn_clicked(); diff --git a/Qt/debugger_memory.cpp b/Qt/debugger_memory.cpp index d044145f5d..d6eeb36b60 100644 --- a/Qt/debugger_memory.cpp +++ b/Qt/debugger_memory.cpp @@ -1,6 +1,5 @@ #include "debugger_memory.h" #include "ui_debugger_memory.h" -#include "EmuThread.h" #include "Core/Debugger/SymbolMap.h" #include @@ -22,22 +21,6 @@ Debugger_Memory::~Debugger_Memory() delete ui; } - -void Debugger_Memory::showEvent(QShowEvent *) -{ - -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif -} - -void Debugger_Memory::releaseLock() -{ - EmuThread_LockDraw(false); -} - void Debugger_Memory::Update() { ui->memView->redraw(); @@ -76,16 +59,14 @@ void Debugger_Memory::NotifyMapLoaded() item->setData(Qt::UserRole, 0x80000000); ui->symbols->addItem(item); - for(int i = 0; i < symbolMap.GetNumSymbols(); i++) - { - if(symbolMap.GetSymbolType(i) & ST_DATA) - { - QListWidgetItem* item = new QListWidgetItem(); - item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QString::number(symbolMap.GetSymbolSize(i)) +")"); - item->setData(Qt::UserRole, symbolMap.GetAddress(i)); - ui->symbols->addItem(item); - } - } + std::vector symbols = symbolMap.GetAllSymbols(ST_DATA); + for(int i = 0; i < (int)symbols.size(); i++) + { + QListWidgetItem* item = new QListWidgetItem(); + item->setText(QString("%1 (%2)").arg(QString::fromStdString(symbols[i].name)).arg(symbols[i].size)); + item->setData(Qt::UserRole, symbols[i].address); + ui->symbols->addItem(item); + } ui->regions->clear(); /* diff --git a/Qt/debugger_memory.h b/Qt/debugger_memory.h index 852b24fc37..c4593a5fef 100644 --- a/Qt/debugger_memory.h +++ b/Qt/debugger_memory.h @@ -22,10 +22,6 @@ public: void Goto(u32 addr); void NotifyMapLoaded(); -public slots: - void releaseLock(); -protected: - void showEvent(QShowEvent *); private slots: void on_editAddress_textChanged(const QString &arg1); diff --git a/Qt/debugger_memorytex.cpp b/Qt/debugger_memorytex.cpp index e3fbc38285..fef57135ed 100644 --- a/Qt/debugger_memorytex.cpp +++ b/Qt/debugger_memorytex.cpp @@ -8,7 +8,6 @@ #include #include "Core/HLE/sceDisplay.h" #include "GPU/GPUInterface.h" -#include "EmuThread.h" #include "base/display.h" Debugger_MemoryTex::Debugger_MemoryTex(QWidget *parent) : @@ -23,23 +22,6 @@ Debugger_MemoryTex::~Debugger_MemoryTex() delete ui; } - -void Debugger_MemoryTex::showEvent(QShowEvent *) -{ - -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif -} - -void Debugger_MemoryTex::releaseLock() -{ - EmuThread_LockDraw(false); -} - - void Debugger_MemoryTex::ShowTex(const GPUgstate &state) { ui->texaddr->setText(QString("%1").arg(state.texaddr[0] & 0xFFFFFF,8,16,QChar('0'))); @@ -58,8 +40,6 @@ void Debugger_MemoryTex::ShowTex(const GPUgstate &state) void Debugger_MemoryTex::on_readBtn_clicked() { - EmuThread_LockDraw(true); - GPUgstate state; state.texaddr[0] = ui->texaddr->text().toUInt(0,16); state.texbufwidth[0] = ui->texbufwidth0->text().toUInt(0,16); @@ -89,7 +69,4 @@ void Debugger_MemoryTex::on_readBtn_clicked() } delete[] newData; - EmuThread_LockDraw(false); - - } diff --git a/Qt/debugger_memorytex.h b/Qt/debugger_memorytex.h index c04677e8d2..a39d3ed53b 100644 --- a/Qt/debugger_memorytex.h +++ b/Qt/debugger_memorytex.h @@ -17,10 +17,7 @@ public: ~Debugger_MemoryTex(); void ShowTex(const GPUgstate& state); -protected: - void showEvent(QShowEvent *); private slots: - void releaseLock(); void on_readBtn_clicked(); private: diff --git a/Qt/debugger_vfpu.cpp b/Qt/debugger_vfpu.cpp index 290dd26f08..af10c2e058 100644 --- a/Qt/debugger_vfpu.cpp +++ b/Qt/debugger_vfpu.cpp @@ -1,6 +1,5 @@ #include "debugger_vfpu.h" #include "ui_debugger_vfpu.h" -#include "EmuThread.h" #include "mainwindow.h" #include @@ -22,22 +21,6 @@ Debugger_VFPU::~Debugger_VFPU() delete ui; } - -void Debugger_VFPU::showEvent(QShowEvent *) -{ - -#ifdef Q_WS_X11 - // Hack to remove the X11 crash with threaded opengl when opening the first dialog - EmuThread_LockDraw(true); - QTimer::singleShot(100, this, SLOT(releaseLock())); -#endif -} - -void Debugger_VFPU::releaseLock() -{ - EmuThread_LockDraw(false); -} - void Debugger_VFPU::Update() { ui->vfpu->redraw(); diff --git a/Qt/debugger_vfpu.h b/Qt/debugger_vfpu.h index c002c9a19d..e14fc73713 100644 --- a/Qt/debugger_vfpu.h +++ b/Qt/debugger_vfpu.h @@ -19,10 +19,6 @@ public: void Update(); void Goto(u32 addr); -protected: - void showEvent(QShowEvent *); -public slots: - void releaseLock(); private slots: void on_comboBox_currentIndexChanged(int index); diff --git a/Qt/desktop_assets.qrc b/Qt/desktop_assets.qrc new file mode 100644 index 0000000000..305c032844 --- /dev/null +++ b/Qt/desktop_assets.qrc @@ -0,0 +1,26 @@ + + + ../assets/ui_atlas_lowmem.zim + ../assets/ppge_atlas.zim + ../lang + ../assets/langregion.ini + ../assets/unknown.png + ../assets/rargray.png + ../assets/zip.png + ../assets/shaders + ../flash0/font + languages/ppsspp_de.qm + languages/ppsspp_en.qm + languages/ppsspp_fr.qm + languages/ppsspp_gr.qm + languages/ppsspp_hu.qm + languages/ppsspp_id.qm + languages/ppsspp_pl.qm + languages/ppsspp_pt-br.qm + languages/ppsspp_ru.qm + languages/ppsspp_zh-cn.qm + languages/ppsspp_zh-tw.qm + resources/breakpointDisable.ico + resources/breakpoint.ico + + diff --git a/Qt/git-version-gen.sh b/Qt/git-version-gen.sh deleted file mode 100755 index d441c38379..0000000000 --- a/Qt/git-version-gen.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -## Copyright (c) 2012- PPSSPP Project. - -## This program is free software: you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation, version 2.0 or later versions. - -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License 2.0 for more details. - -## A copy of the GPL 2.0 should have been included with the program. -## If not, see http://www.gnu.org/licenses/ - -## Official git repository and contact information can be found at -## https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -GIT_VERSION_FILE=$(dirname $0)/../git-version.cpp - -if [ -e "$GIT_VERSION_FILE" ]; then - # Skip updating the file if PPSSPP_GIT_VERSION_NO_UPDATE is 1. - results=$(grep '^#define PPSSPP_GIT_VERSION_NO_UPDATE 1' "$GIT_VERSION_FILE") - if [ "$results" != "" ]; then - exit 0 - fi -fi - -GIT_VERSION=$(git describe --always) -if [ "$GIT_VERSION" == "" ]; then - echo "Unable to update git-version.cpp, git not on path." 1>&2 - - echo "// This is a generated file." > "$GIT_VERSION_FILE" - echo >> "$GIT_VERSION_FILE" - echo 'const char *PPSSPP_GIT_VERSION = "unknown";' >> "$GIT_VERSION_FILE" - exit 0 -fi - -# Don't modify the file if it already has the current version. -if [ -e "$GIT_VERSION_FILE" ]; then - results=$(grep "$GIT_VERSION" "$GIT_VERSION_FILE") - if [ "$results" != "" ]; then - exit 0 - fi -fi - -echo "// This is a generated file." > "$GIT_VERSION_FILE" -echo >> "$GIT_VERSION_FILE" -echo 'const char *PPSSPP_GIT_VERSION = "'"$GIT_VERSION"'";' >> "$GIT_VERSION_FILE" -echo >> "$GIT_VERSION_FILE" -echo "// If you don't want this file to update/recompile, change to 1." >> "$GIT_VERSION_FILE" -echo "#define PPSSPP_GIT_VERSION_NO_UPDATE 0" >> "$GIT_VERSION_FILE" diff --git a/Qt/languages/ppsspp_de.ts b/Qt/languages/ppsspp_de.ts index 5a4ddd6474..375ef6a618 100644 --- a/Qt/languages/ppsspp_de.ts +++ b/Qt/languages/ppsspp_de.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Einstellungen + Einstellungen @@ -58,45 +57,45 @@ - + New function name - + New function name: - + Warning - + Warnung - + No symbol selected - + Kein Symbol gefunden CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -175,7 +174,7 @@ Show VFPU - + Zeige VFPU @@ -195,7 +194,7 @@ Stop - + Stopp @@ -252,7 +251,7 @@ Status - + Status @@ -272,7 +271,7 @@ Name - + Name @@ -285,32 +284,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Warten - + Suspend @@ -320,7 +319,7 @@ Dialog - + Dialog @@ -355,7 +354,7 @@ Stop - Stop + Stopp @@ -365,7 +364,7 @@ Commands - + Kommandos @@ -385,7 +384,7 @@ Textures - + Texturen @@ -414,7 +413,7 @@ Vertex Buffer - + Vertex Buffer @@ -480,7 +479,7 @@ Value - + Wert @@ -500,7 +499,7 @@ Color - + Farbe @@ -510,20 +509,20 @@ Zoom- - + Zoom- Zoom+ - + Zoom+ - + Run to here - + Run to draw using this texture @@ -533,7 +532,7 @@ Dialog - + Dialog @@ -556,7 +555,7 @@ Symbole - + Memory Viewer - %1 @@ -657,662 +656,422 @@ - - GamePadDialog - - - Gamepad Configuration - - - - - GamePad List - - - - - Refresh - - - - - Select - Select - - - - Gamepad Values : - - - - - TextLabel - - - - - Assign Gamepad input - - - - - to PSP button/axis - - - - - Assign - - - - - Press buttons on your gamePad to verify mapping : - - - - - - <b>No gamepad</b> - - - - - <b>Unknown gamepad</b> - - - - - Buttons - - - - - - Button %1 - - - - - Axes - - - - - %1 Neg - - - - - Axes %1 Neg - - - - - %1 Pos - - - - - Axes %1 Pos - - - - - Hats - - - - - <b>Current gamepad: %1</b> - - - MainWindow - PPSSPP PPSSPP - + &File &Datei - + + Quickload State + Schnellladen + + + + Quicksave State + Schnellspeichern + + + &Emulation &Emulation - - Debu&g + + Re&set + Z&urücksetzen + + + + Run on &load - + + Load Map File... + Lade Map-Datei... + + + + Save Map File... + Speichere Map-Datei... + + + + Reset Symbol Table + Setze Symboltabelle zurück + + + + Dump next frame to log + Dump nächsten Frame + + + + Disassembly + Demontage + + + + Display List... + Anzeige Liste... + + + + Log Console + Log-Konsole + + + + Memory View + Speicher-Anzeige + + + + Memory View Texture + Speicher Anzeigen Texturen + + + &Options &Optionen - - G3D - G3D - - - - HLE - HLE - - - - Default - Standard - - - - Lo&g Levels + + &CPU Dynarec - - &Language - &Sprache - - - - &Video - &Video - - - - &Anisotropic filtering - &Anisotrope Filterung - - - - &Zoom - &Zoom - - - - Co&ntrols - Ta&stenbelegung - - - - &Core + + &Vertex Decoder Dynarec - - &Help - &Hilfe + + Fast &Memory (unstable) + Schnellen Speicher (instabil) - - &Open... - &Öffnen... + &Ignore illegal reads/writes + &Ignoriere illegales lesen/schreiben> - - &Close - &Schließen - - - - - - - - - - Quickload state - Schnellladen - - - - F4 - F4 - - - - Quicksave state - Schnellspeichern - - - - F2 - F2 - - - - &Load State File... - &Lade Spielstand... - - - - &Save State File... - &Speichere Spielstand... - - - - E&xit - B&ende - - - - &Run - &Starte - - - - F7 - F7 - - - - &Pause - &Pause - - - - F8 - F8 - - - - R&eset - Z&urücksetzen - - - - &Interpreter - &Interpreter - - - &Slightly Faster Interpreter - &etwas scnellerer Interpreter - - - - &Dynarec - &Dynarec - - - - Load &Map File... - Lade &Map Dateien... - - - - &Save Map File... - &Speichere Map Dateien... - - - - &Reset Symbol Table - &Setze Symboltabelle zurück - - - - &Disassembly - - - - - Ctrl+D - Strg+D - - - - &Log Console - &Log Konsole - - - - Ctrl+L - Strg+L - - - - Memory &View... - - - - - Ctrl+M - Strg+M - - - - &Keyboard - &Tastatur - - - - &Toggle fullscreen - &Vollbild - - - - Show &debug statistics - Zeige &debug Statistiken - - - - I&gnore illegal reads/writes - - - - - &Gamepad - &Gamepad - - - - Run on loa&d - Starte nach dem La&den - - - - Show &FPS counter - Zeige &FPS - - - - S&tretch to display + + &Stretch to Display S&trecke auf Bildschirm - - &Sound emulation - &Ton emulation - - - - F11 - F11 - - - - &Buffered Rendering - &Buffered Rendering - - - - F5 - F5 - - - - &Hardware Transform - &Hardware Transformation - - - - F6 - F6 - - - - &Linear Filtering - &Lineare Filterung - - - - &Wireframe (experimental) - - - - - &Display Raw Framebuffer - - - - - Screen &1x - Anzeigegröße &1x - - - - Ctrl+1 - Strg+1 - - - - Screen &2x - Anzeigegröße &2x - - - - Ctrl+2 - Strg+2 - - - - Screen &3x - Anzeigegröße &3x - - - - Ctrl+3 - Strg+3 - - - - Screen &4x - Anzeigegröße &4x - - - - Ctrl+4 - Strg+4 - - - - &Fast Memory (dynarec, unstable) - &Fast Memory (dynarec, unstable) - - - - &Go to http://www.ppsspp.org/ - &Besuche http://www.ppsspp.org - - - - &About PPSSPP... - &Über PPSSPP... - - - - &Use VBO - &Nutze VBO - - - - - - Debug - Debug - - - - - - Warning - Warnung - - - - - - Error - Fehler - - - - - - Info - Info - - - - D&ump next frame to log - - - - + &Vertex Cache &Vertex Cache - - Memory View Texture... - + + &Frameskip + V&ollbildübersprung - - DisplayList... - + + &Audio + &Audio - - Simple 2xAA - Einfaches 2xAA + + &Fullscreen + Vollbild - - Off - Aus + + &Show debug statistics + Zeige Debug-Statistiken - - 2x - 2x + + &Show FPS + Zeige FPS - - 4x - 4x + G3D + G3D - - 8x - 8x + HLE + HLE - - 16x - 16x + + &Go to official website + &Gehe zur offiziellen Website - - Frameskip - Frameskip + Default + Standard - - Gamepad - Gamepad + + &Language + &Sprache - - You need to compile with SDL to have Gamepad support. - + + &Video + &Video - - No translations - Keine Übersetzung vorhanden - - - - gamepadMapping - - - Cross - Kreuz + &Anisotropic filtering + &Anisotrope Filterung - - Circle - Kreis + &Zoom + &Zoom - - Square - Viereck + Co&ntrols + Ta&stenbelegung - - Triangle - Dreieck + + &Core + &Kern - - Left Trigger - Linke Schultertaste + + &Help + &Hilfe - - Right Trigger - Rechte Schultertaste + + &Open... + &Öffnen... - - Start - Start + + &Close + &Schließen - - Select - Select + Quickload state + Schnellladen - - Up - Hoch + F4 + F4 - - Down - Runter + Quicksave state + Schnellspeichern - - Left - Links + F2 + F2 - - Right - Rechts + + &Load State File... + &Lade Spielstand... - - Home - Home + + &Save State File... + &Speichere Spielstand... - - Stick left - Analogstick links + + E&xit + Schließen - - Stick right - Analogstick rechts + + &Run + &Starte - - Stick up - Analogstick oben + F7 + F7 - - Stick bottom - Analogstick unten + + &Pause + &Pause + + + F8 + F8 + + + &Slightly Faster Interpreter + Etwas schnellerer Interpreter + + + &Dynarec + &Dynarec + + + Load &Map File... + Lade &Map Datei... + + + &Save Map File... + &Speichere Map Datei... + + + &Reset Symbol Table + &Setze Symboltabelle zurück + + + Ctrl+D + Strg+D + + + &Log Console + &Log-Konsole + + + Ctrl+L + Strg+L + + + Ctrl+M + Strg+M + + + &Keyboard + &Tastatur + + + &Toggle fullscreen + &Vollbild + + + Show &debug statistics + Zeige Debug-Statistiken + + + &Gamepad + &Gamepad + + + Run on loa&d + Starte nach dem La&den + + + Show &FPS counter + Zeige &FPS + + + S&tretch to display + S&trecke auf Bildschirm + + + &Sound emulation + &Ton-Emulation + + + F11 + F11 + + + + &Buffered Rendering + &Gepuffert Rendering + + + F5 + F5 + + + + &Hardware Transform + &Hardware Transformation + + + F6 + F6 + + + + &Linear Filtering + &Lineare Filterung + + + Screen &1x + Anzeigegröße &1x + + + Ctrl+1 + Strg+1 + + + Screen &2x + Anzeigegröße &2x + + + Ctrl+2 + Strg+2 + + + Screen &3x + Anzeigegröße &3x + + + Ctrl+3 + Strg+3 + + + Screen &4x + Anzeigegröße &4x + + + Ctrl+4 + Strg+4 + + + &Fast Memory (dynarec, unstable) + Schneller Speicher (instabil) + + + &Go to http://www.ppsspp.org/ + &Besuche http://www.ppsspp.org/ + + + + &About PPSSPP... + &Über PPSSPP... + + + &Use VBO + &Nutze VBO + + + + De&bug + De&buggen + + + + &Ignore Illegal reads/writes + Ignoriere illegales lesen/schreiben + + + + &Anisotropic Filtering + &Anisotrope Filterung + + + + &Screen Size + &Bildschirmgröße + + + + Lo&g levels + Anmelden &Ebenen diff --git a/Qt/languages/ppsspp_en.ts b/Qt/languages/ppsspp_en.ts index e7d0cec575..67c70e576d 100644 --- a/Qt/languages/ppsspp_en.ts +++ b/Qt/languages/ppsspp_en.ts @@ -1,15 +1,6 @@ - - Controls - - - Controls - Controls window title - - - CtrlDisAsmView @@ -58,22 +49,22 @@ - + New function name - + New function name: - + Warning - + No symbol selected @@ -81,22 +72,22 @@ CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +105,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -285,32 +276,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Suspend @@ -518,12 +509,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +547,7 @@ - + Memory Viewer - %1 @@ -657,657 +648,241 @@ - - GamePadDialog - - - Gamepad Configuration - - - - - GamePad List - - - - - Refresh - - - - - Select - - - - - Gamepad Values : - - - - - TextLabel - - - - - Assign Gamepad input - - - - - to PSP button/axis - - - - - Assign - - - - - Press buttons on your gamePad to verify mapping : - - - - - - <b>No gamepad</b> - - - - - <b>Unknown gamepad</b> - - - - - Buttons - - - - - - Button %1 - - - - - Axes - - - - - %1 Neg - - - - - Axes %1 Neg - - - - - %1 Pos - - - - - Axes %1 Pos - - - - - Hats - - - - - <b>Current gamepad: %1</b> - - - MainWindow - - PPSSPP - - - - + &File - + &Emulation - - Debu&g + + Run on &load - + &Options - - G3D + + &CPU Dynarec - - HLE + + &Vertex Decoder Dynarec - - Default - - - - - Lo&g Levels - - - - + &Language - + &Video - - &Anisotropic filtering - - - - - &Zoom - - - - - Co&ntrols - - - - + &Core - + + &Ignore Illegal reads/writes + + + + &Help - + + De&bug + + + + &Open... - + &Close - - - + + Quickload State - - Quickload state + + Quicksave State - - F4 - - - - - Quicksave state - - - - - F2 - - - - + &Load State File... - + &Save State File... - + E&xit - + &Run - - F7 - - - - + &Pause - - F8 + + Re&set - - R&eset + + Load Map File... - - &Interpreter + + Save Map File... - - &Dynarec + + Reset Symbol Table - - Load &Map File... + + Dump next frame to log - - &Save Map File... + + Disassembly - - &Reset Symbol Table + + Display List... - - &Disassembly + + Log Console - - Ctrl+D + + Memory View - - &Log Console + + Memory View Texture - - Ctrl+L + + Fast &Memory (unstable) - - Memory &View... + + &Anisotropic Filtering - - Ctrl+M - - - - - &Keyboard - - - - - &Toggle fullscreen - - - - - Show &debug statistics - - - - - I&gnore illegal reads/writes - - - - - &Gamepad - - - - - Run on loa&d - - - - - Show &FPS counter - - - - - S&tretch to display - - - - - &Sound emulation - - - - - F11 - - - - + &Buffered Rendering - - F5 - - - - - &Hardware Transform - - - - - F6 - - - - + &Linear Filtering - - &Wireframe (experimental) + + &Screen Size - - &Display Raw Framebuffer + + &Stretch to Display - - Screen &1x + + &Hardware Transform - - Ctrl+1 - - - - - Screen &2x - - - - - Ctrl+2 - - - - - Screen &3x - - - - - Ctrl+3 - - - - - Screen &4x - - - - - Ctrl+4 - - - - - &Fast Memory (dynarec, unstable) - - - - - &Go to http://www.ppsspp.org/ - - - - - &About PPSSPP... - - - - - &Use VBO - - - - - - - Debug - - - - - - - Warning - - - - - - - Error - - - - - - - Info - - - - - D&ump next frame to log - - - - + &Vertex Cache - - Memory View Texture... + + &Frameskip - - DisplayList... + + &Audio - - Simple 2xAA + + &Fullscreen - - Off + + &Show debug statistics - - 2x + + &Show FPS - - 4x + + Lo&g levels - - 8x + + &Go to official website - - 16x - - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - - - - - gamepadMapping - - - Cross - - - - - Circle - - - - - Square - - - - - Triangle - - - - - Left Trigger - - - - - Right Trigger - - - - - Start - - - - - Select - - - - - Up - - - - - Down - - - - - Left - - - - - Right - - - - - Home - - - - - Stick left - - - - - Stick right - - - - - Stick up - - - - - Stick bottom + + &About PPSSPP... diff --git a/Qt/languages/ppsspp_fr.ts b/Qt/languages/ppsspp_fr.ts index 3bef4ffe44..e258fb8074 100644 --- a/Qt/languages/ppsspp_fr.ts +++ b/Qt/languages/ppsspp_fr.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Contrôles + Contrôles @@ -58,22 +57,22 @@ - + New function name - + New function name: - + Warning Avertissement - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -285,32 +284,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Suspend @@ -518,12 +517,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +555,7 @@ - + Memory Viewer - %1 @@ -657,277 +656,164 @@ - - GamePadDialog - - - Gamepad Configuration - Configuration du pad - - - - GamePad List - Liste des controlleurs de jeu - - - - Refresh - Rafraîchir - - - - Select - Sélectionner - - - - Gamepad Values : - - - - - TextLabel - - - - - Assign Gamepad input - Assigner la touche du pad - - - - to PSP button/axis - au boutton PSP - - - - Assign - Assigner - - - - Press buttons on your gamePad to verify mapping : - Vérifier les contrôles en appuyant sur les bouttons du pad : - - - - - <b>No gamepad</b> - - - - - <b>Unknown gamepad</b> - - - - - Buttons - - - - - - Button %1 - - - - - Axes - - - - - %1 Neg - - - - - Axes %1 Neg - - - - - %1 Pos - - - - - Axes %1 Pos - - - - - Hats - - - - - <b>Current gamepad: %1</b> - - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File &Fichier - + + Quickload State + + + + + Quicksave State + + + + &Emulation &Emulation - Debu&g - Debu&g + Debu&g - + &Options &Options - G3D - G3D + G3D - HLE - HLE + HLE - Default - Défaut + Défaut - Lo&g Levels - Op&tions du journal + Op&tions du journal - + &Language &Langue - + &Video &Video - &Anisotropic filtering - &Filtrage anisotrope + &Filtrage anisotrope - &Zoom - &Zoom + &Zoom - Co&ntrols - Co&ntrôles + Co&ntrôles - + &Core &Emulation - + + &Ignore Illegal reads/writes + + + + &Help &Aide - + &Open... - &Ouvrir... + &Ouvrir... - + &Close - &Fermer + &Fermer - - - - + - - Quickload state - Chargement rapide + Chargement rapide - F4 - F4 + F4 - Quicksave state - Sauvegarde rapide + Sauvegarde rapide - F2 - F2 + F2 - + &Load State File... - &Charger... + &Charger... - + &Save State File... - &Sauvegarder... + &Sauvegarder... - + E&xit - &Quitter + &Quitter - + &Run - &Démarrer + &Démarrer - F7 - F7 + F7 - + &Pause - &Pause + &Pause - F8 - F8 + F8 - R&eset - R&eset + R&eset - &Interpreter - &Interpreteur + &Interpreteur &Slightly Faster Interpreter @@ -935,385 +821,310 @@ &Interpreteur un peu plus rapide - &Dynarec - &DRC + &DRC - - Load &Map File... - - - - - &Save Map File... - - - - - &Reset Symbol Table - - - - - &Disassembly - - - - Ctrl+D - Ctrl+D + Ctrl+D - &Log Console - &Journal d'événements + &Journal d'événements - Ctrl+L - Ctrl+L + Ctrl+L - - Memory &View... - - - - Ctrl+M - Ctrl+M + Ctrl+M - &Keyboard - &Clavier + &Clavier - &Toggle fullscreen - &Plein écran + &Plein écran - Show &debug statistics - Afficher &les statistiques de débogage + Afficher &les statistiques de débogage - I&gnore illegal reads/writes - I&gnorer les écritures/lectures illégales + I&gnorer les écritures/lectures illégales - &Gamepad - &Pad + &Pad - Run on loa&d - Lancer au cha&rgement + Lancer au cha&rgement - Show &FPS counter - Afficher &les FPS + Afficher &les FPS - S&tretch to display - A&dapter à l'écran + A&dapter à l'écran - &Sound emulation - &Son + &Son - F11 - F11 + F11 - + &Buffered Rendering - &Rendu Tampon + &Rendu Tampon - F5 - F5 + F5 - + &Hardware Transform - &Hardware Transform + &Hardware Transform - F6 - F6 + F6 - + &Linear Filtering - &Filtrage Linéaire + &Filtrage Linéaire - &Wireframe (experimental) - &Rendu en fil de fer (expérimental) + &Rendu en fil de fer (expérimental) - - &Display Raw Framebuffer - - - - Screen &1x - &1x + &1x - Ctrl+1 - Ctrl+1 + Ctrl+1 - Screen &2x - &2x + &2x - Ctrl+2 - Ctrl+2 + Ctrl+2 - Screen &3x - &3x + &3x - Ctrl+3 - Ctrl+3 + Ctrl+3 - Screen &4x - &4x + &4x - Ctrl+4 - Ctrl+4 + Ctrl+4 - &Fast Memory (dynarec, unstable) - &Mémoire Rapide (DRC, instable) + &Mémoire Rapide (DRC, instable) - &Go to http://www.ppsspp.org/ - &Aller à http://www.ppsspp.org/ + &Aller à http://www.ppsspp.org/ - + &About PPSSPP... - &A propos de PPSSPP... + &A propos de PPSSPP... - &Use VBO - &Utiliser les VBO + &Utiliser les VBO - - - - Debug - Débogage - - - - - - Warning - Avertissement - - - - - - Error - Erreur - - - - - - Info - Informations - - - - D&ump next frame to log + + Re&set - + + Run on &load + + + + + De&bug + + + + + Load Map File... + + + + + Save Map File... + + + + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + + &CPU Dynarec + + + + + &Vertex Decoder Dynarec + + + + + Fast &Memory (unstable) + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + &Stretch to Display + + + + &Vertex Cache - &Cache du Vertex + &Cache du Vertex - - Memory View Texture... + + &Frameskip - - DisplayList... + + &Audio + + + + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + Lo&g levels + + + + Debug + Débogage + + + Warning + Avertissement + + + Error + Erreur + + + Info + Informations + + + + &Go to official website - Simple 2xAA - 2x AA + 2x AA - Off - Off + Off - 2x - 2x + 2x - 4x - 4x + 4x - 8x - 8x + 8x - 16x - 16x - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - Pas de traductions - - - - gamepadMapping - - - Cross - Croix - - - - Circle - Rond - - - - Square - Carré - - - - Triangle - Triangle - - - - Left Trigger - Boutton L - - - - Right Trigger - Boutton R - - - - Start - Start - - - - Select - Select - - - - Up - Haut - - - - Down - Bas - - - - Left - Gauche - - - - Right - Droite - - - - Home - Accueil - - - - Stick left - Stick : Gauche - - - - Stick right - Stick : Droite - - - - Stick up - Stick : Haut - - - - Stick bottom - Stick : Bas + 16x diff --git a/Qt/languages/ppsspp_gr.ts b/Qt/languages/ppsspp_gr.ts index a6adbbd1e4..d9ba911d12 100644 --- a/Qt/languages/ppsspp_gr.ts +++ b/Qt/languages/ppsspp_gr.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Τίτλος παραθύρου χειρισμών + Τίτλος παραθύρου χειρισμών @@ -58,22 +57,22 @@ &Μετονομασία λειτουργίας... - + New function name Νέο όνομα λειτουργίας - + New function name: Νέο όνομα λειτουργίας: - + Warning Προειδοποίηση - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm Μετάβαση σε &disasm - + &Copy value &Αντιγραφή τιμής - + C&hange value - + Dump... Αποτύπωση... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view Μετάβαση σε &προβολής μνήμης - + Go to in &disasm Μετάβαση σε &disasm - + &Copy value &Αντιγραφή τιμής - + C&hange... Α&λλαγή... - + Set new value Ορισμός νέας τιμής - + Set new value: Ορισμός νέας τιμής: @@ -285,32 +284,32 @@ Σημείο έναρξης - + Remove breakpoint Αφαίρεση σημείου διακοπής - + Go to entry point Μετάβαση στο σημείο εισόδου - + Change status - + Running Σε λειτουργία - + Wait Αναμονή - + Suspend Αναστολή @@ -518,12 +517,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +555,7 @@ Σύμβολα - + Memory Viewer - %1 Προβολέας Μνήμης - %1 @@ -657,658 +656,402 @@ - - GamePadDialog - - - Gamepad Configuration - Διαμόρφωση Χειριστηρίου - - - - GamePad List - Λίστα Χειριστηρίων - - - - Refresh - Ανανέωση - - - - Select - Επιλογή - - - - Gamepad Values : - Τιμές Χειριστηρίου : - - - - TextLabel - - - - - Assign Gamepad input - Εκχώρηση εισόδου χειριστηρίου - - - - to PSP button/axis - στο κουμί/άξονα PSP - - - - Assign - Εκχώρηση - - - - Press buttons on your gamePad to verify mapping : - Πατήστε τα κουμπιά στο χειριστήριο σας για να επιβεβαιώσετε την αντιστοίχιση: - - - - - <b>No gamepad</b> - <b>Κανένα χειριστήριο</b> - - - - <b>Unknown gamepad</b> - <b>’γνωστο χειριστήριο</b> - - - - Buttons - Πλήκτρα - - - - - Button %1 - Πλήκτρο %1 - - - - Axes - ’ξονες - - - - %1 Neg - %1 Αρν. - - - - Axes %1 Neg - ’ξονες %1 Αρν. - - - - %1 Pos - %1 Θετ. - - - - Axes %1 Pos - ’ξονες %1 Θετ. - - - - Hats - Μοχλοί - - - - <b>Current gamepad: %1</b> - <b>Τρέχον χειριστήριο: %1</b> - - MainWindow - - PPSSPP - - - - + &File &Αρχείο - + + Quickload State + + + + + Quicksave State + + + + &Emulation &Εξομοίωση - Debu&g - Αποσφαλμάτωσ&η + Αποσφαλμάτωσ&η - + &Options &Επιλογές - - G3D - - - - HLE - ΕΥΕ(HLE) + ΕΥΕ(HLE) - Default - Προεπιλογή + Προεπιλογή - Lo&g Levels - Επ&ίπεδα Καταγραφικού + Επ&ίπεδα Καταγραφικού - + &Language &Γλώσσα - + &Video &Βίντεο - &Anisotropic filtering - &Ανισοτροπικό φιτράρισμα + &Ανισοτροπικό φιτράρισμα - &Zoom - &Μεγένθυση + &Μεγένθυση - Co&ntrols - Χε&ιριστήρια + Χε&ιριστήρια - + &Core &Πυρήνας - + + &CPU Dynarec + + + + + &Vertex Decoder Dynarec + + + + + &Ignore Illegal reads/writes + + + + &Help &Βοήθεια - + &Open... - &’νοιγμα... + &’νοιγμα... - + &Close - &Κλείσιμο + &Κλείσιμο - - - - - - - Quickload state - Γρήγορη Φόρτωση + Γρήγορη Φόρτωση - - F4 - - - - Quicksave state - Γρήγορη Αποθήκευση + Γρήγορη Αποθήκευση - - F2 - - - - + &Load State File... - &Φόρτωση Σημείου Αποθήκευσης... + &Φόρτωση Σημείου Αποθήκευσης... - + &Save State File... - &Αποθήκευση Σημείου Αποθήκευσης... + &Αποθήκευση Σημείου Αποθήκευσης... - + E&xit - Έ&ξοδος + Έ&ξοδος - + &Run - &Εκκίνηση + &Εκκίνηση - - F7 - - - - + &Pause - &Παύση + &Παύση - - F8 - - - - R&eset - Ε&πανεκκίνηση + Ε&πανεκκίνηση - - &Interpreter - - - - - &Dynarec - - - - Load &Map File... - Φόρτωση &Αρχείου Χάρτη... + Φόρτωση &Αρχείου Χάρτη... - &Save Map File... - &Αποθήκευση Αρχείου Χάρτη... + &Αποθήκευση Αρχείου Χάρτη... - &Reset Symbol Table - &Επαναφορά Πίνακα Συμβόλων + &Επαναφορά Πίνακα Συμβόλων - &Disassembly - &Αποσυναρμολόγηση + &Αποσυναρμολόγηση - - Ctrl+D - - - - &Log Console - &Κονσόλα Καταγραφέα + &Κονσόλα Καταγραφέα - - Ctrl+L - - - - Memory &View... - Εμφάνιση &Μνήμης... + Εμφάνιση &Μνήμης... - - Ctrl+M - - - - &Keyboard - &Πληκτρολόγιο + &Πληκτρολόγιο - &Toggle fullscreen - &Μετάβαση σε πλήρη οθόνη + &Μετάβαση σε πλήρη οθόνη - Show &debug statistics - Εμφάνιση &στατιστικών αποσφαλμάτωσης + Εμφάνιση &στατιστικών αποσφαλμάτωσης - I&gnore illegal reads/writes - Α&γνόηση αθέμιτων αναγνώσεων + Α&γνόηση αθέμιτων αναγνώσεων - &Gamepad - &Χειριστήριο + &Χειριστήριο - Run on loa&d - Εκκίνηση στην έναρξ&η + Εκκίνηση στην έναρξ&η - Show &FPS counter - Εμφάνιση μετρητή &FPS + Εμφάνιση μετρητή &FPS - S&tretch to display - Ε&πέκταση στην οθόνη + Ε&πέκταση στην οθόνη - &Sound emulation - &Εξομοίωση ήχου + &Εξομοίωση ήχου - - F11 - - - - + &Buffered Rendering - &Buffered Απεικόνιση + &Buffered Απεικόνιση - - F5 - - - - + &Hardware Transform - Hardware Μετασχηματισμός + Hardware Μετασχηματισμός - - F6 - - - - + &Linear Filtering - Γραμμικό φιλτράρισμα + Γραμμικό φιλτράρισμα - &Wireframe (experimental) - Γράφημα Πλέγματος + Γράφημα Πλέγματος - &Display Raw Framebuffer - &Εμφάνιση Ακατέργαστου Framebuffer + &Εμφάνιση Ακατέργαστου Framebuffer - Screen &1x - Οθόνη &1x + Οθόνη &1x - - Ctrl+1 - - - - Screen &2x - Οθόνη &2x + Οθόνη &2x - - Ctrl+2 - - - - Screen &3x - Οθόνη &3x + Οθόνη &3x - - Ctrl+3 - - - - Screen &4x - Οθόνη &4x + Οθόνη &4x - - Ctrl+4 - - - - &Fast Memory (dynarec, unstable) - &Γρήγορη Μνήμη (dynarec, ασταθής) + &Γρήγορη Μνήμη (dynarec, ασταθής) - &Go to http://www.ppsspp.org/ - &Μετάβαση σε http://www.ppsspp.org/ + &Μετάβαση σε http://www.ppsspp.org/ - + &About PPSSPP... - &Περί του PPSSPP... + &Περί του PPSSPP... - &Use VBO - &Χρήση VBO + &Χρήση VBO - - - - Debug - Αποσφαλμάτωση + + Re&set + - - - - Warning - Προειδοποίηση + + Run on &load + - - - - Error - Σφάλμα + + De&bug + - - - - Info - Πληροφορίες + + Load Map File... + - - D&ump next frame to log - Ε&ξαγωγή επόμενου καρέ στον καταγραφέα + + Save Map File... + - + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + + Fast &Memory (unstable) + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + &Stretch to Display + + + + &Vertex Cache - &Προσορηνή Μνήμη Κορυφών + &Προσορηνή Μνήμη Κορυφών + + + + &Frameskip + + + + + &Audio + + + + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + Lo&g levels + + + + Debug + Αποσφαλμάτωση + + + Warning + Προειδοποίηση + + + Error + Σφάλμα + + + Info + Πληροφορίες + + + + &Go to official website + + + + D&ump next frame to log + Ε&ξαγωγή επόμενου καρέ στον καταγραφέα - Memory View Texture... - Προβολή Μνήμης Υφών... - - - - DisplayList... - - - - - Simple 2xAA - Απλό 2xAA - - - - Off - - - - - 2x - - - - - 4x - - - - - 8x - - - - - 16x - - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - Καμία Μετάφραση - - - - gamepadMapping - - - Cross - Χί - - - - Circle - Κύκλος - - - - Square - Τετράγωνο - - - - Triangle - Τρίγωνο - - - - Left Trigger - Αριστερή σκανδάλη - - - - Right Trigger - Δεξιά σκανδάλη - - - - Start - - - - - Select - Επιλογή - - - - Up - Πάνω - - - - Down - Κάτω - - - - Left - Αριστερά - - - - Right - Δεξιά - - - - Home - - - - - Stick left - Αναλογικό αριστερά - - - - Stick right - Αναλογικό δεξιά - - - - Stick up - Αναλογικό πάνω - - - - Stick bottom - Αναλογικό κάτω + Προβολή Μνήμης Υφών... diff --git a/Qt/languages/ppsspp_hu.ts b/Qt/languages/ppsspp_hu.ts index 8bcbfef9bf..e6c8b0a260 100644 --- a/Qt/languages/ppsspp_hu.ts +++ b/Qt/languages/ppsspp_hu.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Írányítás + Írányítás @@ -58,22 +57,22 @@ - + New function name - + New function name: - + Warning - + Figyelmeztetés - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -285,32 +284,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Suspend @@ -518,12 +517,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +555,7 @@ - + Memory Viewer - %1 @@ -657,658 +656,402 @@ - - GamePadDialog - - - Gamepad Configuration - Játékvezérlő Beállítás - - - - GamePad List - Játékvezérlők listája - - - - Refresh - Frissítés - - - - Select - Kiválasztás - - - - Gamepad Values : - Játékvezérlő Értékei : - - - - TextLabel - - - - - Assign Gamepad input - Játékvezérlő Gomb hozzárendelése - - - - to PSP button/axis - PSP gomb/tengelyhez - - - - Assign - Hozzárendelés - - - - Press buttons on your gamePad to verify mapping : - Nyomj meg gombokat a játékvezérlődön a gombok ellenőrzéséhez : - - - - - <b>No gamepad</b> - <b>Nincs Játékvezérlő</b> - - - - <b>Unknown gamepad</b> - <b>Ismeretlen Játékvezérlő</b> - - - - Buttons - Gombok - - - - - Button %1 - Gomb %1 - - - - Axes - Tengelyek - - - - %1 Neg - %1 Neg - - - - Axes %1 Neg - Tengely %1 Neg - - - - %1 Pos - %1 Poz - - - - Axes %1 Pos - Tengely %1 Poz - - - - Hats - - - - - <b>Current gamepad: %1</b> - <b>Jelenlegi Játékvezérlő: %1</b> - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File Fájl - + + Quickload State + + + + + Quicksave State + + + + &Emulation Emuláció - - Debu&g + + Re&set - + + Run on &load + + + + + Load Map File... + + + + + Save Map File... + + + + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + &Options Beállítások - - G3D + + &CPU Dynarec - - HLE + + &Vertex Decoder Dynarec - - Default - Alapértelmezett - - - - Lo&g Levels - Log szint - - - - &Language - Nyelv - - - - &Video - Videó - - - - &Anisotropic filtering - Anizotróp szűrés - - - - &Zoom - Nagyítás - - - - Co&ntrols - Irányítás - - - - &Core - Központi - - - - &Help - Segítség - - - - &Open... - Megnyitás... - - - - &Close - Bezárás - - - - - - - - - - - Quickload state - Állás gyorsbetöltése - - - - F4 - F4 - - - - Quicksave state - Állás gyorsmentése - - - - F2 - F2 - - - - &Load State File... - Állás betöltése... - - - - &Save State File... - Állás mentése... - - - - E&xit - Kilépés - - - - &Run - Futtatás - - - - F7 - F7 - - - - &Pause - Szüneteltetés - - - - F8 - F8 - - - - R&eset - Újraindítás - - - - &Interpreter - Interpreter - - - - &Dynarec - Dynarec - - - - Load &Map File... - Map fájl betöltése... - - - - &Save Map File... - Map fájl mentése... - - - - &Reset Symbol Table + + Fast &Memory (unstable) - - &Disassembly + + &Stretch to Display - - Ctrl+D - Ctrl+D - - - - &Log Console - Log Konzol - - - - Ctrl+L - Ctrl+L - - - - Memory &View... - - - - - Ctrl+M - Ctrl+M - - - - &Keyboard - Billentyűzet - - - - &Toggle fullscreen - Teljesképernyőre váltás - - - - Show &debug statistics - - - - - I&gnore illegal reads/writes - Illegális olvasások/írások mellőzése - - - - &Gamepad - Játékvezérlő - - - - Run on loa&d - Futtatás betöltéskor - - - - Show &FPS counter - FPS számláló mutatása - - - - S&tretch to display - Kép nyújtása - - - - &Sound emulation - Hang emuláció - - - - F11 - F11 - - - - &Buffered Rendering - Pufferelt Renderelés - - - - F5 - F5 - - - - &Hardware Transform - Hardveres Átváltoztatás - - - - F6 - F6 - - - - &Linear Filtering - Lineáris Szűrés - - - - &Wireframe (experimental) - - - - - &Display Raw Framebuffer - - - - - Screen &1x - 1x-es méret - - - - Ctrl+1 - Ctrl+1 - - - - Screen &2x - 2x-es méret - - - - Ctrl+2 - Ctrl+2 - - - - Screen &3x - 3x-os méret - - - - Ctrl+3 - Ctrl+3 - - - - Screen &4x - 4x-es méret - - - - Ctrl+4 - Ctrl+4 - - - - &Fast Memory (dynarec, unstable) - Gyors Memória (dynarec, instabil) - - - - &Go to http://www.ppsspp.org/ - Ugrás a honlapra http//www.ppsspp.org/ - - - - &About PPSSPP... - PPSSPP Névjegye - - - - &Use VBO - VBO Használata - - - - - - Debug - - - - - - - Warning - Figyelmeztetés - - - - - - Error - Hiba - - - - - - Info - Infó - - - - D&ump next frame to log - - - - + &Vertex Cache - - Memory View Texture... + + &Frameskip - - DisplayList... + + &Audio - - Simple 2xAA - Egyszerű 2x-es AA + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + &Go to official website + + + + Default + Alapértelmezett + + + Lo&g Levels + Log szint + + + + &Language + Nyelv + + + + &Video + Videó + + + &Anisotropic filtering + Anizotróp szűrés + + + &Zoom + Nagyítás + + + Co&ntrols + Irányítás + + + + &Core + Központi + + + + &Help + Segítség + + + + &Open... + Megnyitás... + + + + &Close + Bezárás + + + - + - + + + Quickload state + Állás gyorsbetöltése + + + F4 + F4 + + + Quicksave state + Állás gyorsmentése + + + F2 + F2 + + + + &Load State File... + Állás betöltése... + + + + &Save State File... + Állás mentése... + + + + E&xit + Kilépés + + + + &Run + Futtatás + + + F7 + F7 + + + + &Pause + Szüneteltetés + + + F8 + F8 + + + R&eset + Újraindítás + + + &Interpreter + Interpreter + + + &Dynarec + Dynarec + + + Load &Map File... + Map fájl betöltése... + + + &Save Map File... + Map fájl mentése... + + + Ctrl+D + Ctrl+D + + + &Log Console + Log Konzol + + + Ctrl+L + Ctrl+L + + + Ctrl+M + Ctrl+M + + + &Keyboard + Billentyűzet + + + &Toggle fullscreen + Teljesképernyőre váltás + + + I&gnore illegal reads/writes + Illegális olvasások/írások mellőzése + + + &Gamepad + Játékvezérlő + + + Run on loa&d + Futtatás betöltéskor + + + Show &FPS counter + FPS számláló mutatása + + + S&tretch to display + Kép nyújtása + + + &Sound emulation + Hang emuláció + + + + &Buffered Rendering + Pufferelt Renderelés + + + + &Hardware Transform + Hardveres Átváltoztatás + + + F6 + F6 + + + + &Linear Filtering + Lineáris Szűrés + + + &Fast Memory (dynarec, unstable) + Gyors Memória (dynarec, instabil) + + + &Go to http://www.ppsspp.org/ + Ugrás a honlapra http//www.ppsspp.org/ + + + + &About PPSSPP... + PPSSPP Névjegye + + + &Use VBO + VBO Használata + + + + De&bug + + + + + &Ignore Illegal reads/writes + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + Lo&g levels + + + + Warning + Figyelmeztetés + + + Error + Hiba + + + Info + Infó - Off - Ki + Ki - - 2x - 2x - - - - 4x - 4x - - - - 8x - 8x - - - - 16x - 16x - - - Frameskip - Frameskip + Frameskip - - Gamepad - Játékvezérlő - - - You need to compile with SDL to have Gamepad support. - SDL-t kell használnod fordításnál Játékvezérlő támogatásért. - - - - No translations - Nincs Fordítás - - - - gamepadMapping - - - Cross - Kereszt - - - - Circle - Kör - - - - Square - Négyzet - - - - Triangle - Háromszög - - - - Left Trigger - Bal Trigger - - - - Right Trigger - Jobb Trigger - - - - Start - Start - - - - Select - Select - - - - Up - Fel - - - - Down - Le - - - - Left - Bal - - - - Right - Jobb - - - - Home - Home - - - - Stick left - Stick balra - - - - Stick right - Stick jobbra - - - - Stick up - Stick fel - - - - Stick bottom - Stick le + SDL-t kell használnod fordításnál Játékvezérlő támogatásért. diff --git a/Qt/languages/ppsspp_id.ts b/Qt/languages/ppsspp_id.ts index 1e81b5fcc8..b0ed6fe1ef 100644 --- a/Qt/languages/ppsspp_id.ts +++ b/Qt/languages/ppsspp_id.ts @@ -1,15 +1,6 @@ - - Controls - - - Controls - Controls window title - - - CtrlDisAsmView @@ -58,22 +49,22 @@ - + New function name - + New function name: - + Warning Peringatan - + No symbol selected @@ -81,22 +72,22 @@ CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +105,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -285,32 +276,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Suspend @@ -518,12 +509,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +547,7 @@ - + Memory Viewer - %1 @@ -657,658 +648,258 @@ - - GamePadDialog - - - Gamepad Configuration - - - - - GamePad List - - - - - Refresh - - - - - Select - Select - - - - Gamepad Values : - - - - - TextLabel - - - - - Assign Gamepad input - - - - - to PSP button/axis - - - - - Assign - - - - - Press buttons on your gamePad to verify mapping : - - - - - - <b>No gamepad</b> - - - - - <b>Unknown gamepad</b> - - - - - Buttons - Tombol - - - - - Button %1 - - - - - Axes - - - - - %1 Neg - - - - - Axes %1 Neg - - - - - %1 Pos - - - - - Axes %1 Pos - - - - - Hats - - - - - <b>Current gamepad: %1</b> - - - MainWindow - - PPSSPP - - - - + &File - + &Emulation - - Debu&g + + Run on &load - + &Options - - G3D + + &CPU Dynarec - - HLE + + &Vertex Decoder Dynarec - - Default - - - - - Lo&g Levels - - - - + &Language - + &Video - - &Anisotropic filtering - - - - - &Zoom - - - - - Co&ntrols - - - - + &Core - + + &Ignore Illegal reads/writes + + + + &Help - + + De&bug + + + + &Open... - + &Close - - - + + Quickload State - - Quickload state + + Quicksave State - - F4 - - - - - Quicksave state - - - - - F2 - - - - + &Load State File... - + &Save State File... - + E&xit - + &Run - - F7 - - - - + &Pause - - F8 + + Re&set - - R&eset + + Load Map File... - - &Interpreter + + Save Map File... - - &Dynarec + + Reset Symbol Table - - Load &Map File... + + Dump next frame to log - - &Save Map File... + + Disassembly - - &Reset Symbol Table + + Display List... - - &Disassembly + + Log Console - - Ctrl+D + + Memory View - - &Log Console + + Memory View Texture - - Ctrl+L + + Fast &Memory (unstable) - - Memory &View... + + &Anisotropic Filtering - - Ctrl+M - - - - - &Keyboard - - - - - &Toggle fullscreen - - - - - Show &debug statistics - - - - - I&gnore illegal reads/writes - - - - - &Gamepad - - - - - Run on loa&d - - - - - Show &FPS counter - - - - - S&tretch to display - - - - - &Sound emulation - - - - - F11 - - - - + &Buffered Rendering - - F5 - - - - - &Hardware Transform - - - - - F6 - - - - + &Linear Filtering - - &Wireframe (experimental) + + &Screen Size - - &Display Raw Framebuffer + + &Stretch to Display - - Screen &1x + + &Hardware Transform - - Ctrl+1 - - - - - Screen &2x - - - - - Ctrl+2 - - - - - Screen &3x - - - - - Ctrl+3 - - - - - Screen &4x - - - - - Ctrl+4 - - - - - &Fast Memory (dynarec, unstable) - - - - - &Go to http://www.ppsspp.org/ - - - - - &About PPSSPP... - - - - - &Use VBO - - - - - - - Debug - - - - - - - Warning - Peringatan - - - - - - Error - Galat - - - - - - Info - Informasi - - - - D&ump next frame to log - - - - + &Vertex Cache - - Memory View Texture... + + &Frameskip - - DisplayList... + + &Audio - - Simple 2xAA + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + Lo&g levels + + + + Warning + Peringatan + + + Error + Galat + + + Info + Informasi + + + + &Go to official website + + + + + &About PPSSPP... - Off - Mati - - - - 2x - - - - - 4x - - - - - 8x - - - - - 16x - - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - Tak ada terjemahan - - - - gamepadMapping - - - Cross - Silang - - - - Circle - Bundar - - - - Square - Kotak - - - - Triangle - Segitiga - - - - Left Trigger - Trigger Kiri - - - - Right Trigger - Trigger Kanan - - - - Start - Start - - - - Select - Select - - - - Up - Atas - - - - Down - Bawah - - - - Left - Kiri - - - - Right - Kanan - - - - Home - Beranda - - - - Stick left - Stick kiri - - - - Stick right - Stick kanan - - - - Stick up - Stick atas - - - - Stick bottom - Stick bawah + Mati diff --git a/Qt/languages/ppsspp_pl.ts b/Qt/languages/ppsspp_pl.ts index 213fb8cb84..dc10e59518 100644 --- a/Qt/languages/ppsspp_pl.ts +++ b/Qt/languages/ppsspp_pl.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Układ klawiszy + Układ klawiszy @@ -58,22 +57,22 @@ &Zmień nazwę funkcji... - + New function name Nowa nazwa funkcji - + New function name: Nowa nazwa funkcji: - + Warning Ostrzeżenia - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm &Przejdź do deasemblera - + &Copy value &Kopiuj wartość - + C&hange value - + Dump... Zrzut... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view Przejdź do widoku &pamięci - + Go to in &disasm Przejdź do &deasemblera - + &Copy value &Kopiuj wartość - + C&hange... &Zmień... - + Set new value Ustaw nową wartość - + Set new value: Ustaw nową wartość: @@ -293,32 +292,32 @@ Punkt wejścia - + Remove breakpoint Usuń breakpoint - + Go to entry point Przejdź do punktu wejścia - + Change status - + Running Działający - + Wait Czekający - + Suspend Uśpiony @@ -530,12 +529,12 @@ - + Run to here - + Run to draw using this texture @@ -568,7 +567,7 @@ Symboliczny - + Memory Viewer - %1 Widok pamięci - %1 @@ -669,662 +668,478 @@ - - GamePadDialog - - - Gamepad Configuration - Konfiguracja kontrolera - - - - GamePad List - Lista kontrolerów - - - - Refresh - Odśwież - - - - Select - Wybierz - - - - Gamepad Values : - Wartości przycisków/osi: - - - - TextLabel - - - - - Assign Gamepad input - Przypisz przycisk - - - - to PSP button/axis - do przycisku/osi PSP - - - - Assign - Przypisz - - - - Press buttons on your gamePad to verify mapping : - Naciśnij przyciski na kontrolerze: - - - - - <b>No gamepad</b> - <b>Nie wykryto pada</b> - - - - <b>Unknown gamepad</b> - <b>Nieznany pad</b> - - - - Buttons - Przyciski - - - - - Button %1 - Przycisk %1 - - - - Axes - Osie - - - - %1 Neg - %1 zanegowany - - - - Axes %1 Neg - Oś %1 zanegowana - - - - %1 Pos - %1 pozycja - - - - Axes %1 Pos - Pozycja osi %1 - - - - Hats - Haty - - - - <b>Current gamepad: %1</b> - <b>Wybrany pad: %1</b> - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File &Plik - + + Quickload State + + + + + Quicksave State + + + + &Emulation &Emulacja - Debu&g - &Debugger + &Debugger - + &Options &Opcje - G3D - G3D + G3D - HLE - HLE + HLE - Default - Domyślne + Domyślne - Lo&g Levels - &Poziomy logowania + &Poziomy logowania - + &Language &Język - + &Video &Wideo - &Anisotropic filtering - &Filtrowanie anizotropowe + &Filtrowanie anizotropowe - &Zoom - &Powiększenie + &Powiększenie - Co&ntrols - S&terowanie + S&terowanie - + &Core Jądr&o - + + &Ignore Illegal reads/writes + + + + &Help Pomo&c - + &Open... - &Otwórz... + &Otwórz... - + &Close - &Zamknij + &Zamknij - - - - - - - Quickload state - Wczytaj stan + Wczytaj stan - F4 - F4 + F4 - Quicksave state - Zapisz stan + Zapisz stan - F2 - F2 + F2 - + &Load State File... - &Wczytaj plik stanu... + &Wczytaj plik stanu... - + &Save State File... - &Zapisz plik stanu... + &Zapisz plik stanu... - + E&xit - Wyj&dź + Wyj&dź - + &Run - &Uruchom + &Uruchom - F7 - F7 + F7 - + &Pause - &Pauza + &Pauza - F8 - F8 + F8 - R&eset - &Reset + &Reset - &Interpreter - &Interpreter + &Interpreter &Slightly Faster Interpreter &Szybszy interpreter - &Dynarec - R&ekompilacja (Dynarec) + R&ekompilacja (Dynarec) - Load &Map File... - &Wczytaj plik mapy... + &Wczytaj plik mapy... - &Save Map File... - &Zapisz plik mapy... + &Zapisz plik mapy... - &Reset Symbol Table - Zresetuj &tablicę symboli + Zresetuj &tablicę symboli - &Disassembly - &Deasembler + &Deasembler - Ctrl+D - Ctrl+D + Ctrl+D - &Log Console - &Konsola logowania + &Konsola logowania - Ctrl+L - Ctrl+L + Ctrl+L - Memory &View... - Widok &pamięci... + Widok &pamięci... - Ctrl+M - Ctrl+M + Ctrl+M - &Keyboard - &Klawiatura + &Klawiatura - &Toggle fullscreen - Pełny &ekran + Pełny &ekran - Show &debug statistics - Pokaż &statystyki + Pokaż &statystyki - I&gnore illegal reads/writes - I&gnoruj błędne odczyty/zapisy + I&gnoruj błędne odczyty/zapisy - &Gamepad - &Pad + &Pad - Run on loa&d - Uruchom po &załadowaniu + Uruchom po &załadowaniu - Show &FPS counter - Pokaż licznik &FPS + Pokaż licznik &FPS - S&tretch to display - &Rozciągnij obraz + &Rozciągnij obraz - &Sound emulation - &Emulacja dźwięku + &Emulacja dźwięku - F11 - F11 + F11 - + &Buffered Rendering - &Buforowane renderowanie + &Buforowane renderowanie - F5 - F5 + F5 - + &Hardware Transform - Sprzętowa &transformacja + Sprzętowa &transformacja - F6 - F6 + F6 - + &Linear Filtering - Filtrowanie &liniowe + Filtrowanie &liniowe - &Wireframe (experimental) - &Widok siatki (eksperymentalny) + &Widok siatki (eksperymentalny) - &Display Raw Framebuffer - Wyświetl &surowy framebuffer + Wyświetl &surowy framebuffer - Screen &1x - &1x + &1x - Ctrl+1 - Ctrl+1 + Ctrl+1 - Screen &2x - &2x + &2x - Ctrl+2 - Ctrl+2 + Ctrl+2 - Screen &3x - &3x + &3x - Ctrl+3 - Ctrl+3 + Ctrl+3 - Screen &4x - &4x + &4x - Ctrl+4 - Ctrl+4 + Ctrl+4 - &Fast Memory (dynarec, unstable) - S&zybka pamięć (wymagany Dynarec, niestabilne) + S&zybka pamięć (wymagany Dynarec, niestabilne) - &Go to http://www.ppsspp.org/ - &Idź do http://www.ppsspp.org + &Idź do http://www.ppsspp.org - + &About PPSSPP... - &O PPSSPP... + &O PPSSPP... - &Use VBO - Użyj &VBO + Użyj &VBO - - - - Debug - Debug + + Re&set + - - - - Warning - Ostrzeżenia + + Run on &load + - - - - Error - Błędy + + De&bug + - - - - Info - Info + + Load Map File... + - - D&ump next frame to log - Z&rzuć następną ramkę do logu + + Save Map File... + - + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + + &CPU Dynarec + + + + + &Vertex Decoder Dynarec + + + + + Fast &Memory (unstable) + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + &Stretch to Display + + + + &Vertex Cache - &Cache wierzchołków + &Cache wierzchołków - - Memory View Texture... + + &Frameskip - - DisplayList... + + &Audio - - Simple 2xAA - Prosty antyaliasing 2x + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + Lo&g levels + + + + Debug + Debug + + + Warning + Ostrzeżenia + + + Error + Błędy + + + Info + Info + + + + &Go to official website + + + + D&ump next frame to log + Z&rzuć następną ramkę do logu - Off - Wyłączone - - - - 2x - 2x - - - - 4x - 4x - - - - 8x - 8x - - - - 16x - 16x - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - Brak tłumaczeń - - - - gamepadMapping - - - Cross - Krzyżyk - - - - Circle - Kółko - - - - Square - Kwadrat - - - - Triangle - Trójkąt - - - - Left Trigger - Lewy trigger - - - - Right Trigger - Prawy trigger - - - - Start - Start - - - - Select - Select - - - - Up - Góra - - - - Down - Dół - - - - Left - Lewo - - - - Right - Prawo - - - - Home - Klawisz Home - - - - Stick left - Lewo (analog) - - - - Stick right - Prawo (analog) - - - - Stick up - Góra (analog) - - - - Stick bottom - Dół (analog) + Wyłączone diff --git a/Qt/languages/ppsspp_pt-br.ts b/Qt/languages/ppsspp_pt-br.ts index 8c5a56c311..39dd5b7451 100644 --- a/Qt/languages/ppsspp_pt-br.ts +++ b/Qt/languages/ppsspp_pt-br.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Controles + Controles @@ -58,22 +57,22 @@ &Renomear função... - + New function name Novo nome de função - + New function name: Novo nome de função: - + Warning Atenção - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm Vá para &disasm - + &Copy value &Copiar valor - + C&hange value - + Dump... Despejar... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view Vá para o visualizador de &memória - + Go to in &disasm Vá para o &disasm - + &Copy value &Copiar valor - + C&hange... &Trocar... - + Set new value Setar novo valor - + Set new value: Setar novo valor: @@ -293,32 +292,32 @@ Ponto de entrada - + Remove breakpoint Remover breakpoint - + Go to entry point Ir para ponto de entrada - + Change status - + Running Rodando - + Wait Esperando - + Suspend Suspenso @@ -530,12 +529,12 @@ - + Run to here - + Run to draw using this texture @@ -568,7 +567,7 @@ Símbolos - + Memory Viewer - %1 Visualizador de Memória - %1 @@ -669,662 +668,402 @@ - - GamePadDialog - - - Gamepad Configuration - Configuração do Gamepad - - - - GamePad List - Lista de Gamepads - - - - Refresh - Atualizar - - - - Select - Selecionar - - - - Gamepad Values : - Valores de Gamepad : - - - - TextLabel - - - - - Assign Gamepad input - Atribuir entrada do Gamepad - - - - to PSP button/axis - para o botão/eixo do PSP - - - - Assign - Atribuir - - - - Press buttons on your gamePad to verify mapping : - Pressione botões no seu Gamepad para verificar o mapeamento : - - - - - <b>No gamepad</b> - Sem Gamepad - - - - <b>Unknown gamepad</b> - Gamepad desconhecido - - - - Buttons - Botões - - - - - Button %1 - Botões %1 - - - - Axes - Eixos - - - - %1 Neg - - - - - Axes %1 Neg - Eixos %1 Neg - - - - %1 Pos - - - - - Axes %1 Pos - Eixos %1 Pos - - - - Hats - - - - - <b>Current gamepad: %1</b> - <b>Gamepad atual: %1</b> - - MainWindow - - PPSSPP - - - - + &File &Arquivo - + + Quickload State + + + + + Quicksave State + + + + &Emulation &Emulação - - Debu&g - + + Re&set + - + + Run on &load + + + + + Load Map File... + + + + + Save Map File... + + + + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + &Options &Opções - - G3D - + + &CPU Dynarec + - - HLE - + + &Vertex Decoder Dynarec + + + + + Fast &Memory (unstable) + + + + + &Stretch to Display + + + + + &Vertex Cache + Cache de &Vértices + + + + &Frameskip + + + + + &Audio + + + + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + &Go to official website + - Default - Padrão + Padrão - Lo&g Levels - Nível de Lo&g + Nível de Lo&g - + &Language &Linguagem - + &Video &Vídeo - &Anisotropic filtering - Filtragem &Anisotrópica + Filtragem &Anisotrópica - - &Zoom - - - - Co&ntrols - Co&ntroles + Co&ntroles - + &Core &Núcleo - + &Help Aj&uda - + &Open... - &Abrir... + &Abrir... - + &Close - &Fechar + &Fechar - - - - - - - Quickload state - Carregar estado rápido + Carregar estado rápido - - F4 - - - - Quicksave state - Salvar estado rápido + Salvar estado rápido - - F2 - - - - + &Load State File... - &Carregar estado do arquivo... + &Carregar estado do arquivo... - + &Save State File... - &Salvar estado no arquivo... + &Salvar estado no arquivo... - + E&xit - Sai&r + Sai&r - + &Run - &Rodar + &Rodar - - F7 - - - - + &Pause - &Pausar + &Pausar - - F8 - - - - R&eset - R&esetar + R&esetar - &Interpreter - &Interpretador + &Interpretador &Slightly Faster Interpreter Interpretador um &pouco mais rápido - &Dynarec - Recompilador &dinâmico + Recompilador &dinâmico - Load &Map File... - Carregar &mapa do arquivo... + Carregar &mapa do arquivo... - &Save Map File... - &Salvar mapa no arquivo... + &Salvar mapa no arquivo... - &Reset Symbol Table - &Reiniciar tabela de símbolos + &Reiniciar tabela de símbolos - - &Disassembly - - - - Ctrl+D - L + L - &Log Console - Console de &Logs + Console de &Logs - Ctrl+L - L + L - Memory &View... - &Visualizador de Memória... + &Visualizador de Memória... - - Ctrl+M - - - - &Keyboard - &Teclado + &Teclado - &Toggle fullscreen - Tela &cheia + Tela &cheia - Show &debug statistics - Mostrar estatísticas de &debug + Mostrar estatísticas de &debug - I&gnore illegal reads/writes - I&gnorar leituras/escritas ilegais + I&gnorar leituras/escritas ilegais - - &Gamepad - - - - Run on loa&d - Rodar ao &abrir + Rodar ao &abrir - Show &FPS counter - Mostrar contador de &FPS + Mostrar contador de &FPS - S&tretch to display - Es&ticar tela + Es&ticar tela - &Sound emulation - Emular &som + Emular &som - - F11 - - - - + &Buffered Rendering - Renderização com &buffer + Renderização com &buffer - - F5 - - - - + &Hardware Transform - Transformação em &Hardware + Transformação em &Hardware - - F6 - - - - + &Linear Filtering - Filtragem &Linear + Filtragem &Linear - &Wireframe (experimental) - &Wireframe (experimental) + &Wireframe (experimental) - &Display Raw Framebuffer - Mostrar framebuffer &bruto + Mostrar framebuffer &bruto - Screen &1x - &1x Tela + &1x Tela - - Ctrl+1 - - - - Screen &2x - &2x Tela + &2x Tela - - Ctrl+2 - - - - Screen &3x - &3x Tela + &3x Tela - - Ctrl+3 - - - - Screen &4x - &4x Tela + &4x Tela - - Ctrl+4 - - - - &Fast Memory (dynarec, unstable) - Memória &rápida (recompilador dinâmico, instável) + Memória &rápida (recompilador dinâmico, instável) - &Go to http://www.ppsspp.org/ - &Ir para http://www.ppsspp.org/ + &Ir para http://www.ppsspp.org/ - + &About PPSSPP... - &Sobre o PPSSPP... + &Sobre o PPSSPP... - &Use VBO - &Usar VBO + &Usar VBO - - - - Debug - + + De&bug + + + + + &Ignore Illegal reads/writes + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + Lo&g levels + - - - Warning - Atenção + Atenção - - - Error - Erro + Erro - - - Info - Informação + Informação - D&ump next frame to log - D&espejar o próximo frame no log + D&espejar o próximo frame no log - - &Vertex Cache - Cache de &Vértices - - - Memory View Texture... - Ver texturas na memória... + Ver texturas na memória... - - DisplayList... - - - - - Simple 2xAA - Simples 2xAA - - - Off - Desligar - - - - 2x - - - - - 4x - - - - - 8x - - - - - 16x - - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - Sem tradução - - - - gamepadMapping - - - Cross - X - - - - Circle - Círculo - - - - Square - Quadrado - - - - Triangle - Triângulo - - - - Left Trigger - Gatilho Esquerdo - - - - Right Trigger - Gatilho Direito - - - - Start - - - - - Select - - - - - Up - Cima - - - - Down - Baixo - - - - Left - Esquerda - - - - Right - Direita - - - - Home - - - - - Stick left - Analógico Esquerda - - - - Stick right - Analógico Direita - - - - Stick up - Analógico Cima - - - - Stick bottom - Analógico Baixo + Desligar diff --git a/Qt/languages/ppsspp_ru.ts b/Qt/languages/ppsspp_ru.ts index f4d1babe7a..66eda9c6e3 100644 --- a/Qt/languages/ppsspp_ru.ts +++ b/Qt/languages/ppsspp_ru.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - Управление + Управление @@ -58,22 +57,22 @@ - + New function name - + New function name: - + Warning - + Предупреждение - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm - + &Copy value - + C&hange value - + Dump... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view - + Go to in &disasm - + &Copy value - + C&hange... - + Set new value - + Set new value: @@ -285,32 +284,32 @@ - + Remove breakpoint - + Go to entry point - + Change status - + Running - + Wait - + Suspend @@ -518,12 +517,12 @@ - + Run to here - + Run to draw using this texture @@ -556,7 +555,7 @@ - + Memory Viewer - %1 @@ -657,662 +656,434 @@ - - GamePadDialog - - - Gamepad Configuration - Настройка геймпада - - - - GamePad List - Список геймпадов - - - - Refresh - Обновить - - - - Select - Выбрать - - - - Gamepad Values : - Значения геймпадов : - - - - TextLabel - - - - - Assign Gamepad input - Выбрать ввод геймпада - - - - to PSP button/axis - для кнопок PSP - - - - Assign - Выбрать - - - - Press buttons on your gamePad to verify mapping : - Нажмите кнопки для проверки геймпада : - - - - - <b>No gamepad</b> - <b>Геймпад не найден</b> - - - - <b>Unknown gamepad</b> - <b>Неизвестный геймпад</b> - - - - Buttons - Кнопки - - - - - Button %1 - Кнопка %1 - - - - Axes - Оси - - - - %1 Neg - %1 отрицательно - - - - Axes %1 Neg - Ось %1 отрицательна - - - - %1 Pos - %1 положительно - - - - Axes %1 Pos - Ось %1 положительна - - - - Hats - - - - - <b>Current gamepad: %1</b> - <b>Текущий геймпад: %1</b> - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File &Файл - + + Quickload State + Быстро загрузить состояние + + + + Quicksave State + Быстро сохранить состояние + + + &Emulation &Эмуляция - Debu&g - &Отладка + &Отладка - + &Options &Настройки - G3D - G3D + G3D - HLE - HLE + HLE - Default - По умолчанию + По умолчанию - Lo&g Levels - Уровень ло&гирования + Уровень ло&гирования - + &Language &Язык - + &Video &Видео - &Anisotropic filtering - &Анизотропная фильтрация + &Анизотропная фильтрация - &Zoom - &Экран + &Экран - Co&ntrols - У&правление + У&правление - + &Core &Ядро - + + &Ignore Illegal reads/writes + &Игнорировать неправильные чтения/запись + + + &Help &Помощь - + &Open... &Открыть... - + &Close &Закрыть - - - - + - - Quickload state - Быстро загрузить состояние + Быстро загрузить состояние - - F4 - F4 - - - Quicksave state - Быстро сохранить состояние + Быстро сохранить состояние - F2 - F2 + F2 - + &Load State File... &Открыть файл состояния... - + &Save State File... &Сохранить файл состояния... - + E&xit В&ыход - + &Run &Запустить - - F7 - F7 - - - + &Pause &Пауза - - F8 - F8 - - - R&eset - Пере&загрузить + Пере&загрузить - - &Interpreter - &Интерпретатор - - - &Slightly Faster Interpreter - &etwas scnellerer Interpreter - - - &Dynarec - &Dynarec + &Dynarec - Load &Map File... - Загрузить файл &карты... + Загрузить файл &карты... - &Save Map File... - &Сохранить файл карты... + &Сохранить файл карты... - &Reset Symbol Table - &Сбросить таблицу символов + &Сбросить таблицу символов - &Disassembly - &Деасэмблинг + &Деасэмблинг - - Ctrl+D - Ctrl+D - - - &Log Console - &Консоль логов + &Консоль логов - - Ctrl+L - Ctrl+L - - - Memory &View... - &Отображение памяти... + &Отображение памяти... - - Ctrl+M - Ctrl+M - - - &Keyboard - &Клавиатура + &Клавиатура - &Toggle fullscreen - &Полный экран + &Полный экран - Show &debug statistics - Показывать &отладочную информацию + Показывать &отладочную информацию - I&gnore illegal reads/writes - &Игнорировать неправильные чтения/запись + &Игнорировать неправильные чтения/запись - &Gamepad - &Геймпад + &Геймпад - Run on loa&d - Запускать при &загрузке + Запускать при &загрузке - Show &FPS counter - Показывать &FPS + Показывать &FPS - S&tretch to display - За&стягивать под экран + За&стягивать под экран - &Sound emulation - Эмуляция &звука + Эмуляция &звука - - F11 - F11 - - - + &Buffered Rendering &Буферированный рендеринг - F5 - F5 + F5 - + &Hardware Transform &Аппаратное преобразование - F6 - F6 + F6 - + &Linear Filtering &Линейная фильтрация - &Wireframe (experimental) - &Отображать каркас (экспериментально) + &Отображать каркас (экспериментально) - &Display Raw Framebuffer - &Отображать буфер кадров + &Отображать буфер кадров - Screen &1x - Увеличить &1x + Увеличить &1x - - Ctrl+1 - Ctrl+1 - - - - Screen &2x - Увеличить &2x - - - - Ctrl+2 - Ctrl+2 - - - - Screen &3x - Увеличить &3x - - - - Ctrl+3 - Ctrl+3 - - - - Screen &4x - Увеличить &4x - - - - Ctrl+4 - Ctrl+4 - - - &Fast Memory (dynarec, unstable) - &Быстрая память (dynarec, нестабильно) + &Быстрая память (dynarec, нестабильно) - - &Go to http://www.ppsspp.org/ - &Веб сайт http://www.ppsspp.org - - - + &About PPSSPP... &О PPSSPP... - &Use VBO - &Использовать VBO + &Использовать VBO - - - - Debug - Отладка + + Re&set + Пере&загрузить - - - - Warning - Предупреждение + + Run on &load + Запускать при &загрузке - - - - Error - Ошибка + + De&bug + &Отладка - - - - Info - Информация + + Load Map File... + Загрузить файл &карты... - - D&ump next frame to log + + Save Map File... + &Сохранить файл карты... + + + + Reset Symbol Table + &Сбросить таблицу символов + + + + Dump next frame to log С&бросить следующий кадр в лог - + + Disassembly + &Деасэмблинг + + + + Display List... + Список экранов... + + + + Log Console + &Консоль логов + + + + Memory View + &Отображение памяти + + + + Memory View Texture + Память отображаемых текстур + + + + &CPU Dynarec + &Dynarec + + + + &Vertex Decoder Dynarec + + + + + Fast &Memory (unstable) + &Быстрая память (нестабильно) + + + + &Anisotropic Filtering + &Анизотропная фильтрация + + + + &Screen Size + (&S)Размер экрана + + + + &Stretch to Display + За&стягивать под экран + + + &Vertex Cache &Vertex кэш - - Memory View Texture... - Память отображаемых текстур... - - - - DisplayList... - Список экранов... - - - - Simple 2xAA - Простое 2x сглаживание - - - - Off - Выключено - - - - 2x - 2x - - - - 4x - 4x - - - - 8x - 8x - - - - 16x - 16x - - - - Frameskip + + &Frameskip Пропуск кадров - - Gamepad - Геймпад + + &Audio + &Aудио + + + + &Fullscreen + &Полный экран + + + + &Show debug statistics + Показывать &отладочную информацию + + + + &Show FPS + Показывать &FPS + + + + Lo&g levels + Уровень ло&гирования + + + Debug + Отладка + + + Warning + Предупреждение + + + Error + Ошибка + + + Info + Информация + + + + &Go to official website + (&G)Зайдите на официальный сайт + + + D&ump next frame to log + С&бросить следующий кадр в лог + + + Memory View Texture... + Память отображаемых текстур... + + + DisplayList... + Список экранов... + + + Simple 2xAA + Простое 2x сглаживание + + + Off + Выключено + + + Frameskip + Пропуск кадров - You need to compile with SDL to have Gamepad support. - Вам нужно скомпилировать с SDL чтобы иметь поддержку геймпада. - - - - No translations - Нет перевода - - - - gamepadMapping - - - Cross - Крест - - - - Circle - Круг - - - - Square - Квадрат - - - - Triangle - Треугольник - - - - Left Trigger - Левый курок - - - - Right Trigger - Правый курок - - - - Start - Старт - - - - Select - Выбор - - - - Up - Вверх - - - - Down - Вниз - - - - Left - Влево - - - - Right - Вправо - - - - Home - Домой - - - - Stick left - Стик влево - - - - Stick right - Стик вправо - - - - Stick up - Стик вверх - - - - Stick bottom - Стик вниз + Вам нужно скомпилировать с SDL чтобы иметь поддержку геймпада. diff --git a/Qt/languages/ppsspp_cn.ts b/Qt/languages/ppsspp_zh-cn.ts similarity index 64% rename from Qt/languages/ppsspp_cn.ts rename to Qt/languages/ppsspp_zh-cn.ts index 2a4b7f1621..46e5101474 100644 --- a/Qt/languages/ppsspp_cn.ts +++ b/Qt/languages/ppsspp_zh-cn.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - 控制器 + 控制器 @@ -58,45 +57,45 @@ (&R)重命名函数... - + New function name 新函数名称 - + New function name: 新函数名称: - + Warning - 警告 + 警告 - + No symbol selected - + 没有选择象征 CtrlMemView - + Go to in &disasm (&D)转到汇编视图 - + &Copy value (&C)复制值 - + C&hange value - + Dump... 转储... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view (&M)转到内存视图 - + Go to in &disasm (&D)转到汇编视图 - + &Copy value (&C)复制值 - + C&hange... (&H)更改... - + Set new value 设置新值 - + Set new value: 设置新值: @@ -293,32 +292,32 @@ 入口点 - + Remove breakpoint 移除断点 - + Go to entry point 转到入口点 - + Change status - + Running 执行中 - + Wait 等待 - + Suspend 挂起 @@ -530,12 +529,12 @@ - + Run to here - + Run to draw using this texture @@ -568,7 +567,7 @@ 特征符模式 - + Memory Viewer - %1 内存查看器 - %1 @@ -669,663 +668,478 @@ 整型 - - GamePadDialog - - - Gamepad Configuration - 手柄设置 - - - - GamePad List - 手柄列表 - - - - Refresh - 刷新 - - - - Select - 选中 - - - - Gamepad Values : - 手柄值: - - - - TextLabel - TextLabel - TextLabel - - - - Assign Gamepad input - 指定该手柄 - - - - to PSP button/axis - 作为PSP按键/摇杆输入 - - - - Assign - 指定 - - - - Press buttons on your gamePad to verify mapping : - 按下手柄按键来确认键位映射: - - - - - <b>No gamepad</b> - <b>未发现手柄</b> - - - - <b>Unknown gamepad</b> - <b>未识别的手柄</b> - - - - Buttons - 按钮 - - - - - Button %1 - 按钮 %1 - - - - Axes - 摇杆 - - - - %1 Neg - %1 Neg - - - - Axes %1 Neg - Axes %1 Neg - - - - %1 Pos - %1 Pos - - - - Axes %1 Pos - Axes %1 Pos - - - - Hats - Hats - - - - <b>Current gamepad: %1</b> - <b>当前手柄: %1</b> - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File (&F)文件 - + + Quickload State + 快速负载态 + + + + Quicksave State + 快速保存态 + + + &Emulation (&E)模拟 - Debu&g - (&G)调试 + (&G)调试 - + &Options (&O)选项 - - G3D - - - - - HLE - - - - Default - 默认 + 默认 - Lo&g Levels - (&G)日志级别 + (&G)日志级别 - + &Language (&L)语言选择 - + &Video (&V)视频 - &Anisotropic filtering - (&A)各向异性过滤 + (&A)各向异性过滤 - &Zoom - (&Z)缩放 + (&Z)缩放 - Co&ntrols - (&N)控制 + (&N)控制 - + &Core (&C)核心 - + + &Ignore Illegal reads/writes + 忽略非法读取/写入 + + + &Help (&H)帮助 - + &Open... (&O)打开... - + &Close (&C)关闭 - - - - + - - Quickload state - 快速读档 + 快速读档 - F4 - F4 + F4 - Quicksave state - 快速存档 + 快速存档 - F2 - F2 + F2 - + &Load State File... (&L)读取存档... - + &Save State File... (&S)保存存档... - + E&xit (&X)退出 - + &Run (&R)运行 - F7 - F7 + F7 - + &Pause (&P)暂停 - F8 - F8 + F8 - R&eset - (&E)重置 + (&E)重置 - &Interpreter - (&I)解释器 + (&I)解释器 &Slightly Faster Interpreter (&S)较快的解释器 - &Dynarec - (&D)动态重编译 + (&D)动态重编译 - Load &Map File... - (&M)读取Map文件... + (&M)读取Map文件... - &Save Map File... - (&S)保存Map文件... + (&S)保存Map文件... - &Reset Symbol Table - (&R)重置符号表 + (&R)重置符号表 - &Disassembly - (&D)汇编视图 + (&D)汇编视图 - Ctrl+D - Ctrl+D + Ctrl+D - &Log Console - (&L)查看控制台日志 + (&L)查看控制台日志 - Ctrl+L - Ctrl+L + Ctrl+L - Memory &View... - (&V)内存视图... + (&V)内存视图... - Ctrl+M - Ctrl+M + Ctrl+M - &Keyboard - (&K)键盘 + (&K)键盘 - &Toggle fullscreen - (&T)全屏 + (&T)全屏 - Show &debug statistics - (&D)显示调试信息 + (&D)显示调试信息 - I&gnore illegal reads/writes - (&G)忽略非法读写 + (&G)忽略非法读写 - &Gamepad - (&G)手柄 + (&G)手柄 - Run on loa&d - (&D)载入时运行 + (&D)载入时运行 - Show &FPS counter - (&F)显示帧率计数器 + (&F)显示帧率计数器 - S&tretch to display - (&T)拉伸显示 + (&T)拉伸显示 - &Sound emulation - (&S)模拟声音 + (&S)模拟声音 - F11 - F11 + F11 - + &Buffered Rendering (&B)渲染缓冲 - F5 - F5 + F5 - + &Hardware Transform (&H)硬件加速 - F6 - F6 + F6 - + &Linear Filtering (&L)线性过滤 - &Wireframe (experimental) - (&W)使用线框 (实验性选项) + (&W)使用线框 (实验性选项) - &Display Raw Framebuffer - (&D)显示 Raw 原始缓冲 + (&D)显示 Raw 原始缓冲 - Screen &1x - &1倍窗口 + &1倍窗口 - Ctrl+1 - Ctrl+1 + Ctrl+1 - Screen &2x - &2倍窗口 + &2倍窗口 - Ctrl+2 - Ctrl+2 + Ctrl+2 - Screen &3x - &3倍窗口 + &3倍窗口 - Ctrl+3 - Ctrl+3 + Ctrl+3 - Screen &4x - &4倍窗口 + &4倍窗口 - Ctrl+4 - Ctrl+4 + Ctrl+4 - &Fast Memory (dynarec, unstable) - (&F)高速闪存 (动态重编译,不稳定) + (&F)高速闪存 (动态重编译,不稳定) - &Go to http://www.ppsspp.org/ - (&G)转到 http://www.ppsspp.org/ + (&G)转到 http://www.ppsspp.org/ - + &About PPSSPP... (&A)关于 PPSSPP... - &Use VBO - (&U)使用 VBO + (&U)使用 VBO - - - - Debug + + Re&set + (&R)复位 + + + + Run on &load + 加载时执行 + + + + De&bug 调试 - - - - Warning - 警告 + + Load Map File... + 载入地图文件 - - - - Error - 错误 + + Save Map File... + 保存地图文件 - - - - Info - 信息 + + Reset Symbol Table + 重置符号表 - - D&ump next frame to log - (&U)将下一帧转储至日志 + + Dump next frame to log + 将下一帧转储至日志 - + + Disassembly + 汇编视图 + + + + Display List... + 显示列表... + + + + Log Console + 查看控制台日志 + + + + Memory View + 内存视图 + + + + Memory View Texture + 内存纹理视图 + + + + &CPU Dynarec + (&D)动态重编译 + + + + &Vertex Decoder Dynarec + 顶点解码器动态重编译 + + + + Fast &Memory (unstable) + (&F)高速闪存 (动态重编译,不稳定) + + + + &Anisotropic Filtering + (&A)各向异性过滤 + + + + &Screen Size + 屏幕尺寸 + + + + &Stretch to Display + (&T)拉伸显示 + + + &Vertex Cache (&V)顶点缓存 - + + &Frameskip + (&F)跳帧 + + + + &Audio + (&S)声响 + + + + &Fullscreen + (&F)全屏 + + + + &Show debug statistics + (&D)显示调试信息 + + + + &Show FPS + (&F)显示帧率计数器 + + + + Lo&g levels + (&G)日志级别 + + + Debug + 调试 + + + Warning + 警告 + + + Error + 错误 + + + Info + 信息 + + + + &Go to official website + (&G)进入官方网站 + + + D&ump next frame to log + (&U)将下一帧转储至日志 + + Memory View Texture... - 内存纹理视图... + 内存纹理视图... - - DisplayList... - - - - - Simple 2xAA - - - - Off - 关闭 - - - - 2x - 2x - - - - 4x - 4x - - - - 8x - 8x - - - - 16x - 16x - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - 未翻译 - - - - gamepadMapping - - - Cross - × - - - - Circle - - - - - Square - - - - - Triangle - - - - - Left Trigger - L - - - - Right Trigger - R - - - - Start - 开始 - - - - Select - 选择 - - - - Up - - - - - Down - - - - - Left - - - - - Right - - - - - Home - Home - - - - Stick left - 摇杆左 - - - - Stick right - 摇杆右 - - - - Stick up - 摇杆上 - - - - Stick bottom - 摇杆下 + 关闭 diff --git a/Qt/languages/ppsspp_tc.ts b/Qt/languages/ppsspp_zh-tw.ts similarity index 62% rename from Qt/languages/ppsspp_tc.ts rename to Qt/languages/ppsspp_zh-tw.ts index e1d9147757..3cbe6185dd 100644 --- a/Qt/languages/ppsspp_tc.ts +++ b/Qt/languages/ppsspp_zh-tw.ts @@ -4,10 +4,9 @@ Controls - Controls Controls window title - 控制器 + 控制器 @@ -58,22 +57,22 @@ (&R)重命名函數... - + New function name 新函數名稱 - + New function name: 新函數名稱: - + Warning 警告 - + No symbol selected @@ -81,22 +80,22 @@ CtrlMemView - + Go to in &disasm (&D)轉到彙編視圖 - + &Copy value (&C)複製值 - + C&hange value - + Dump... 轉儲... @@ -114,32 +113,32 @@ CtrlRegisterList - + Go to in &memory view (&M)轉到內存視圖 - + Go to in &disasm (&D)轉到彙編視圖 - + &Copy value (&C)複製值 - + C&hange... (&H)更改... - + Set new value 設置新值 - + Set new value: 設置新值: @@ -293,32 +292,32 @@ 入口點 - + Remove breakpoint 移除斷點 - + Go to entry point 轉到入口點 - + Change status - + Running 執行中 - + Wait 等待 - + Suspend 掛起 @@ -530,12 +529,12 @@ - + Run to here - + Run to draw using this texture @@ -568,7 +567,7 @@ 特徵符模式 - + Memory Viewer - %1 內存查看器 - %1 @@ -669,663 +668,478 @@ 整型 - - GamePadDialog - - - Gamepad Configuration - 手柄設置 - - - - GamePad List - 手柄列表 - - - - Refresh - 刷新 - - - - Select - 選中 - - - - Gamepad Values : - 手柄值: - - - - TextLabel - TextLabel - TextLabel - - - - Assign Gamepad input - 指定該手柄 - - - - to PSP button/axis - 作為PSP按鍵/搖桿輸入 - - - - Assign - 指定 - - - - Press buttons on your gamePad to verify mapping : - 按下手柄按鍵來確認鍵位映射: - - - - - <b>No gamepad</b> - <b>未發現手柄</b> - - - - <b>Unknown gamepad</b> - <b>未識別的手柄</b> - - - - Buttons - 按鈕 - - - - - Button %1 - 按鈕 %1 - - - - Axes - 搖桿 - - - - %1 Neg - %1 Neg - - - - Axes %1 Neg - Axes %1 Neg - - - - %1 Pos - %1 Pos - - - - Axes %1 Pos - Axes %1 Pos - - - - Hats - Hats - - - - <b>Current gamepad: %1</b> - <b>當前手柄: %1</b> - - MainWindow - PPSSPP - PPSSPP + PPSSPP - + &File (&F)文件 - + + Quickload State + + + + + Quicksave State + + + + &Emulation (&E)模擬 - Debu&g - (&G)調試 + (&G)調試 - + &Options (&O)選項 - - G3D - - - - - HLE - - - - Default - 默認 + 默認 - Lo&g Levels - (&G)日誌級別 + (&G)日誌級別 - + &Language (&L)語言選擇 - + &Video (&V)視頻 - &Anisotropic filtering - (&A)各向異性過濾 + (&A)各向異性過濾 - &Zoom - (&Z)縮放 + (&Z)縮放 - Co&ntrols - (&N)控制 + (&N)控制 - + &Core (&C)核心 - + + &Ignore Illegal reads/writes + + + + &Help (&H)幫助 - + &Open... - (&O)打開... + (&O)打開... - + &Close - (&C)關閉 + (&C)關閉 - - - - + - - Quickload state - 快速讀檔 + 快速讀檔 - F4 - F4 + F4 - Quicksave state - 快速存檔 + 快速存檔 - F2 - F2 + F2 - + &Load State File... - (&L)讀取存檔... + (&L)讀取存檔... - + &Save State File... - (&S)保存存檔... + (&S)保存存檔... - + E&xit - (&X)退出 + (&X)退出 - + &Run - (&R)運行 + (&R)運行 - F7 - F7 + F7 - + &Pause - (&P)暫停 + (&P)暫停 - F8 - F8 + F8 - R&eset - (&E)重置 + (&E)重置 - &Interpreter - (&I)解釋器 + (&I)解釋器 &Slightly Faster Interpreter (&S)較快的解釋器 - &Dynarec - (&D)動態重編譯 + (&D)動態重編譯 - Load &Map File... - (&M)讀取Map文件... + (&M)讀取Map文件... - &Save Map File... - (&S)保存Map文件... + (&S)保存Map文件... - &Reset Symbol Table - (&R)重置符號表 + (&R)重置符號表 - &Disassembly - (&D)彙編視圖 + (&D)彙編視圖 - Ctrl+D - Ctrl+D + Ctrl+D - &Log Console - (&L)查看控制台日誌 + (&L)查看控制台日誌 - Ctrl+L - Ctrl+L + Ctrl+L - Memory &View... - (&V)內存視圖... + (&V)內存視圖... - Ctrl+M - Ctrl+M + Ctrl+M - &Keyboard - (&K)鍵盤 + (&K)鍵盤 - &Toggle fullscreen - (&T)全屏 + (&T)全屏 - Show &debug statistics - (&D)顯示調試信息 + (&D)顯示調試信息 - I&gnore illegal reads/writes - (&G)忽略非法讀寫 + (&G)忽略非法讀寫 - &Gamepad - (&G)手柄 + (&G)手柄 - Run on loa&d - (&D)載入時運行 + (&D)載入時運行 - Show &FPS counter - (&F)顯示幀率計數器 + (&F)顯示幀率計數器 - S&tretch to display - (&T)拉伸顯示 + (&T)拉伸顯示 - &Sound emulation - (&S)模擬聲音 + (&S)模擬聲音 - F11 - F11 + F11 - + &Buffered Rendering - (&B)渲染緩衝 + (&B)渲染緩衝 - F5 - F5 + F5 - + &Hardware Transform - (&H)硬件加速 + (&H)硬件加速 - F6 - F6 + F6 - + &Linear Filtering - (&L)線性過濾 + (&L)線性過濾 - &Wireframe (experimental) - (&W)使用線框 (實驗性選項) + (&W)使用線框 (實驗性選項) - &Display Raw Framebuffer - (&D)顯示 Raw 原始緩衝 + (&D)顯示 Raw 原始緩衝 - Screen &1x - &1倍窗口 + &1倍窗口 - Ctrl+1 - Ctrl+1 + Ctrl+1 - Screen &2x - &2倍窗口 + &2倍窗口 - Ctrl+2 - Ctrl+2 + Ctrl+2 - Screen &3x - &3倍窗口 + &3倍窗口 - Ctrl+3 - Ctrl+3 + Ctrl+3 - Screen &4x - &4倍窗口 + &4倍窗口 - Ctrl+4 - Ctrl+4 + Ctrl+4 - &Fast Memory (dynarec, unstable) - (&F)高速閃存 (動態重編譯,不穩定) + (&F)高速閃存 (動態重編譯,不穩定) - &Go to http://www.ppsspp.org/ - (&G)轉到 http://www.ppsspp.org/ + (&G)轉到 http://www.ppsspp.org/ - + &About PPSSPP... - (&A)關於 PPSSPP... + (&A)關於 PPSSPP... - &Use VBO - (&U)使用 VBO + (&U)使用 VBO - - - - Debug - 調試 + + Re&set + - - - - Warning - 警告 + + Run on &load + - - - - Error - 錯誤 + + De&bug + - - - - Info - 信息 + + Load Map File... + - - D&ump next frame to log - (&U)將下一幀轉儲至日誌 + + Save Map File... + - + + Reset Symbol Table + + + + + Dump next frame to log + + + + + Disassembly + + + + + Display List... + + + + + Log Console + + + + + Memory View + + + + + Memory View Texture + + + + + &CPU Dynarec + + + + + &Vertex Decoder Dynarec + + + + + Fast &Memory (unstable) + + + + + &Anisotropic Filtering + + + + + &Screen Size + + + + + &Stretch to Display + + + + &Vertex Cache - (&V)頂點緩存 + (&V)頂點緩存 + + + + &Frameskip + + + + + &Audio + + + + + &Fullscreen + + + + + &Show debug statistics + + + + + &Show FPS + + + + + Lo&g levels + + + + Debug + 調試 + + + Warning + 警告 + + + Error + 錯誤 + + + Info + 信息 + + + + &Go to official website + + + + D&ump next frame to log + (&U)將下一幀轉儲至日誌 - Memory View Texture... - 內存紋理視圖... + 內存紋理視圖... - - DisplayList... - - - - - Simple 2xAA - - - - Off - 關閉 - - - - 2x - 2x - - - - 4x - 4x - - - - 8x - 8x - - - - 16x - 16x - - - - Frameskip - - - - - Gamepad - - - - - You need to compile with SDL to have Gamepad support. - - - - - No translations - 未翻譯 - - - - gamepadMapping - - - Cross - × - - - - Circle - - - - - Square - - - - - Triangle - - - - - Left Trigger - L - - - - Right Trigger - R - - - - Start - 開始 - - - - Select - 選擇 - - - - Up - - - - - Down - - - - - Left - - - - - Right - - - - - Home - Home - - - - Stick left - 搖桿左 - - - - Stick right - 搖桿右 - - - - Stick up - 搖桿上 - - - - Stick bottom - 搖桿下 + 關閉 diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 0caf9a68ab..b93ae73c21 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -1,33 +1,25 @@ +// Qt Desktop UI: works on Linux, Windows and Mac OSX #include "mainwindow.h" -#include "ui_mainwindow.h" +#include +#include +#include #include #include -#include -#include -#include -#include #include "Core/MIPS/MIPSDebugInterface.h" #include "Core/Debugger/SymbolMap.h" #include "Core/SaveState.h" #include "Core/System.h" -#include "Core/Config.h" -#include "ConsoleListener.h" #include "base/display.h" -#include "base/NKCodeFromQt.h" #include "GPU/GPUInterface.h" #include "UI/GamepadEmu.h" #include "QtHost.h" -#include "EmuThread.h" -// TODO: Make this class thread-aware. Can't send events to a different thread. Currently only works on X11. -// Needs to use QueuedConnection for signals/slots. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - ui(new Ui::MainWindow), - timer(this), + currentLanguage("en"), nextState(CORE_POWERDOWN), lastUIState(UISTATE_MENU), dialogDisasm(0), @@ -35,42 +27,19 @@ MainWindow::MainWindow(QWidget *parent) : memoryTexWindow(0), displaylistWindow(0) { - ui->setupUi(this); - host = new QtHost(this); - emugl = ui->widget; - emugl->init(&input_state); - emugl->resize(pixel_xres, pixel_yres); - emugl->setMinimumSize(pixel_xres, pixel_yres); - emugl->setMaximumSize(pixel_xres, pixel_yres); - QObject::connect( emugl, SIGNAL(doubleClick()), this, SLOT(on_action_OptionsFullScreen_triggered()) ); + emugl = new MainUI(this); - createLanguageMenu(); - UpdateMenus(); + setCentralWidget(emugl); + createMenus(); + updateMenus(); - int zoom = g_Config.iInternalResolution; - if (zoom < 1) zoom = 1; - if (zoom > 4) zoom = 4; - SetZoom(zoom); + SetZoom(g_Config.iInternalResolution); SetGameTitle(fileToStart); - connect(&timer, SIGNAL(timeout()), this, SLOT(Update())); - timer.setInterval(0); - timer.start(); - -// if (!fileToStart.isNull()) -// { -// UpdateMenus(); - -// if (stateToLoad != NULL) -// SaveState::Load(stateToLoad); -// } -} - -MainWindow::~MainWindow() -{ - delete ui; + QObject::connect(emugl, SIGNAL(doubleClick()), this, SLOT(fullscrAct())); + QObject::connect(emugl, SIGNAL(newFrame()), this, SLOT(newFrame())); } void MainWindow::ShowMemory(u32 addr) @@ -85,10 +54,8 @@ inline float clamp1(float x) { return x; } -void MainWindow::Update() +void MainWindow::newFrame() { - emugl->updateGL(); - if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !QApplication::overrideCursor() && !g_Config.bShowTouchControls) @@ -96,104 +63,50 @@ void MainWindow::Update() if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen && QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); - UpdateMenus(); + updateMenus(); } } -void MainWindow::UpdateMenus() +void MainWindow::updateMenus() { - bool enable = globalUIState == UISTATE_MENU; - ui->action_FileLoad->setEnabled(enable); - ui->action_FileClose->setEnabled(!enable); - ui->action_FileSaveStateFile->setEnabled(!enable); - ui->action_FileLoadStateFile->setEnabled(!enable); - ui->action_FileQuickloadState->setEnabled(!enable); - ui->action_FileQuickSaveState->setEnabled(!enable); - ui->action_CPUDynarec->setEnabled(enable); - ui->action_CPUInterpreter->setEnabled(enable); - ui->action_DebugDumpFrame->setEnabled(!enable); - ui->action_DebugDisassembly->setEnabled(!enable); - ui->action_DebugMemoryView->setEnabled(!enable); - ui->action_DebugMemoryViewTexture->setEnabled(!enable); - ui->action_DebugDisplayList->setEnabled(!enable); - - ui->action_EmulationRun->setEnabled(Core_IsStepping() || globalUIState == UISTATE_PAUSEMENU); - ui->action_EmulationPause->setEnabled(globalUIState == UISTATE_INGAME); - ui->action_EmulationReset->setEnabled(globalUIState == UISTATE_INGAME); - - // checking - ui->action_EmulationRunLoad->setChecked(g_Config.bAutoRun); - - ui->action_CPUInterpreter->setChecked(!g_Config.bJit); - ui->action_CPUDynarec->setChecked(g_Config.bJit); - ui->action_OptionsFastMemory->setChecked(g_Config.bFastMemory); - ui->action_OptionsIgnoreIllegalReadsWrites->setChecked(g_Config.bIgnoreBadMemAccess); - - ui->action_AFOff->setChecked(g_Config.iAnisotropyLevel == 0); - ui->action_AF2x->setChecked(g_Config.iAnisotropyLevel == 2); - ui->action_AF4x->setChecked(g_Config.iAnisotropyLevel == 4); - ui->action_AF8x->setChecked(g_Config.iAnisotropyLevel == 8); - ui->action_AF16x->setChecked(g_Config.iAnisotropyLevel == 16); - - ui->action_OptionsBufferedRendering->setChecked(g_Config.iRenderingMode == 1); - ui->action_OptionsLinearFiltering->setChecked(3 == g_Config.iTexFiltering); - - ui->action_OptionsScreen1x->setChecked(0 == (g_Config.iInternalResolution - 1)); - ui->action_OptionsScreen2x->setChecked(1 == (g_Config.iInternalResolution - 1)); - ui->action_OptionsScreen3x->setChecked(2 == (g_Config.iInternalResolution - 1)); - ui->action_OptionsScreen4x->setChecked(3 == (g_Config.iInternalResolution - 1)); - - ui->action_Stretch_to_display->setChecked(g_Config.bStretchToDisplay); - ui->action_OptionsHardwareTransform->setChecked(g_Config.bHardwareTransform); - ui->action_OptionsVertexCache->setChecked(g_Config.bVertexCache); - ui->actionFrameskip->setChecked(g_Config.iFrameSkip != 0); - - ui->action_Sound->setChecked(g_Config.bEnableSound); - - ui->action_OptionsShowDebugStatistics->setChecked(g_Config.bShowDebugStats); - ui->action_Show_FPS_counter->setChecked(g_Config.iShowFPSCounter); - - ui->actionLogDefDebug->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LDEBUG); - ui->actionLogDefInfo->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LINFO); - ui->actionLogDefWarning->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LWARNING); - ui->actionLogDefError->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LERROR); - - ui->actionLogG3DDebug->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::G3D) == LogTypes::LDEBUG); - ui->actionLogG3DInfo->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::G3D) == LogTypes::LINFO); - ui->actionLogG3DWarning->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::G3D) == LogTypes::LWARNING); - ui->actionLogG3DError->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::G3D) == LogTypes::LERROR); - - ui->actionLogHLEDebug->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::HLE) == LogTypes::LDEBUG); - ui->actionLogHLEInfo->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::HLE) == LogTypes::LINFO); - ui->actionLogHLEWarning->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::HLE) == LogTypes::LWARNING); - ui->actionLogHLEError->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::HLE) == LogTypes::LERROR); -} - -void MainWindow::changeEvent(QEvent *e) -{ - if (e->type() == QEvent::LanguageChange) - ui->retranslateUi(this); -} - -void MainWindow::closeEvent(QCloseEvent *) -{ - on_action_FileExit_triggered(); -} - -void MainWindow::keyPressEvent(QKeyEvent *e) -{ - if(isFullScreen() && e->key() == Qt::Key_F11) - { - on_action_OptionsFullScreen_triggered(); - return; + foreach(QAction * action, anisotropicGroup->actions()) { + if (g_Config.iAnisotropyLevel == action->data().toInt()) { + action->setChecked(true); + break; + } } - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(e->key())->second, KEY_DOWN)); -} + foreach(QAction * action, screenGroup->actions()) { + if (g_Config.iInternalResolution == action->data().toInt()) { + action->setChecked(true); + break; + } + } -void MainWindow::keyReleaseEvent(QKeyEvent *e) -{ - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(e->key())->second, KEY_UP)); + int defaultLevel = LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON); + foreach(QAction * action, defaultLogGroup->actions()) { + if (defaultLevel == action->data().toInt()) { + action->setChecked(true); + break; + } + } + + int g3dLevel = LogManager::GetInstance()->GetLogLevel(LogTypes::G3D); + foreach(QAction * action, g3dLogGroup->actions()) { + if (g3dLevel == action->data().toInt()) { + action->setChecked(true); + break; + } + } + + int hleLevel = LogManager::GetInstance()->GetLogLevel(LogTypes::HLE); + foreach(QAction * action, hleLogGroup->actions()) { + if (hleLevel == action->data().toInt()) { + action->setChecked(true); + break; + } + } + emit updateMenu(); } /* SLOTS */ @@ -204,7 +117,7 @@ void MainWindow::Boot() dialogDisasm->show(); if(g_Config.bFullScreen != isFullScreen()) - on_action_OptionsFullScreen_triggered(); + fullscrAct(); memoryWindow = new Debugger_Memory(currentDebugMIPS, this, this); memoryTexWindow = new Debugger_MemoryTex(this); @@ -213,17 +126,11 @@ void MainWindow::Boot() notifyMapsLoaded(); if (nextState == CORE_RUNNING) - on_action_EmulationRun_triggered(); - UpdateMenus(); + runAct(); + updateMenus(); } -void MainWindow::CoreEmitWait(bool isWaiting) -{ - // Unlock mutex while core is waiting; - EmuThread_LockDraw(!isWaiting); -} - -void MainWindow::on_action_FileLoad_triggered() +void MainWindow::openAct() { QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)"); if (QFile::exists(filename)) @@ -232,10 +139,9 @@ void MainWindow::on_action_FileLoad_triggered() g_Config.currentDirectory = info.absolutePath().toStdString(); NativeMessageReceived("boot", filename.toStdString().c_str()); } - UpdateMenus(); } -void MainWindow::on_action_FileClose_triggered() +void MainWindow::closeAct() { if(dialogDisasm) dialogDisasm->Stop(); @@ -251,7 +157,6 @@ void MainWindow::on_action_FileClose_triggered() NativeMessageReceived("stop", ""); SetGameTitle(""); - UpdateMenus(); } void SaveStateActionFinished(bool result, void *userdata) @@ -267,17 +172,17 @@ void SaveStateActionFinished(bool result, void *userdata) } } -void MainWindow::on_action_FileQuickloadState_triggered() +void MainWindow::qlstateAct() { SaveState::LoadSlot(0, SaveStateActionFinished, this); } -void MainWindow::on_action_FileQuickSaveState_triggered() +void MainWindow::qsstateAct() { SaveState::SaveSlot(0, SaveStateActionFinished, this); } -void MainWindow::on_action_FileLoadStateFile_triggered() +void MainWindow::lstateAct() { QFileDialog dialog(0,"Load state"); dialog.setFileMode(QFileDialog::ExistingFile); @@ -292,7 +197,7 @@ void MainWindow::on_action_FileLoadStateFile_triggered() } } -void MainWindow::on_action_FileSaveStateFile_triggered() +void MainWindow::sstateAct() { QFileDialog dialog(0,"Save state"); dialog.setFileMode(QFileDialog::AnyFile); @@ -307,23 +212,23 @@ void MainWindow::on_action_FileSaveStateFile_triggered() } } -void MainWindow::on_action_FileExit_triggered() +void MainWindow::exitAct() { - on_action_FileClose_triggered(); + closeAct(); QApplication::exit(0); } -void MainWindow::on_action_EmulationRun_triggered() +void MainWindow::runAct() { NativeMessageReceived("run", ""); } -void MainWindow::on_action_EmulationPause_triggered() +void MainWindow::pauseAct() { NativeMessageReceived("pause", ""); } -void MainWindow::on_action_EmulationReset_triggered() +void MainWindow::resetAct() { if(dialogDisasm) dialogDisasm->Stop(); @@ -340,13 +245,12 @@ void MainWindow::on_action_EmulationReset_triggered() NativeMessageReceived("reset", ""); } -void MainWindow::on_action_EmulationRunLoad_triggered() +void MainWindow::runonloadAct() { g_Config.bAutoRun = !g_Config.bAutoRun; - UpdateMenus(); } -void MainWindow::on_action_DebugLoadMapFile_triggered() +void MainWindow::lmapAct() { QFileDialog dialog(0,"Load .MAP"); dialog.setFileMode(QFileDialog::ExistingFile); @@ -363,7 +267,7 @@ void MainWindow::on_action_DebugLoadMapFile_triggered() } } -void MainWindow::on_action_DebugSaveMapFile_triggered() +void MainWindow::smapAct() { QFileDialog dialog(0,"Save .MAP"); dialog.setFileMode(QFileDialog::AnyFile); @@ -379,210 +283,76 @@ void MainWindow::on_action_DebugSaveMapFile_triggered() } } -void MainWindow::on_action_DebugResetSymbolTable_triggered() +void MainWindow::resetTableAct() { symbolMap.Clear(); notifyMapsLoaded(); } -void MainWindow::on_action_DebugDumpFrame_triggered() +void MainWindow::dumpNextAct() { gpu->DumpNextFrame(); } -void MainWindow::on_action_DebugDisassembly_triggered() +void MainWindow::disasmAct() { if(dialogDisasm) dialogDisasm->show(); } -void MainWindow::on_action_DebugDisplayList_triggered() +void MainWindow::dpyListAct() { if(displaylistWindow) displaylistWindow->show(); } -void MainWindow::on_action_DebugLog_triggered() +void MainWindow::consoleAct() { LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden()); } -void MainWindow::on_action_DebugMemoryView_triggered() +void MainWindow::memviewAct() { if (memoryWindow) memoryWindow->show(); } -void MainWindow::on_action_DebugMemoryViewTexture_triggered() +void MainWindow::memviewTexAct() { if(memoryTexWindow) memoryTexWindow->show(); } -void MainWindow::on_action_CPUDynarec_triggered() -{ - g_Config.bJit = true; - UpdateMenus(); -} - -void MainWindow::on_action_CPUInterpreter_triggered() -{ - g_Config.bJit = false; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsFastMemory_triggered() -{ - g_Config.bFastMemory = !g_Config.bFastMemory; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsIgnoreIllegalReadsWrites_triggered() -{ - g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess; - UpdateMenus(); -} - -void MainWindow::on_action_AFOff_triggered() -{ - g_Config.iAnisotropyLevel = 0; - UpdateMenus(); -} - -void MainWindow::on_action_AF2x_triggered() -{ - g_Config.iAnisotropyLevel = 2; - UpdateMenus(); -} - -void MainWindow::on_action_AF4x_triggered() -{ - g_Config.iAnisotropyLevel = 4; - UpdateMenus(); -} - -void MainWindow::on_action_AF8x_triggered() -{ - g_Config.iAnisotropyLevel = 8; - UpdateMenus(); -} - -void MainWindow::on_action_AF16x_triggered() -{ - g_Config.iAnisotropyLevel = 16; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsBufferedRendering_triggered() -{ - g_Config.iRenderingMode = !g_Config.iRenderingMode; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsLinearFiltering_triggered() -{ - if (g_Config.iTexFiltering == 0) - g_Config.iTexFiltering = 3; - else - g_Config.iTexFiltering = 0; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsScreen1x_triggered() -{ - SetZoom(1); - UpdateMenus(); -} - -void MainWindow::on_action_OptionsScreen2x_triggered() -{ - SetZoom(2); - UpdateMenus(); -} - -void MainWindow::on_action_OptionsScreen3x_triggered() -{ - SetZoom(3); - UpdateMenus(); -} - -void MainWindow::on_action_OptionsScreen4x_triggered() -{ - SetZoom(4); - UpdateMenus(); -} - -void MainWindow::on_action_Stretch_to_display_triggered() +void MainWindow::stretchAct() { g_Config.bStretchToDisplay = !g_Config.bStretchToDisplay; - UpdateMenus(); if (gpu) gpu->Resized(); } -void MainWindow::on_action_OptionsHardwareTransform_triggered() -{ - g_Config.bHardwareTransform = !g_Config.bHardwareTransform; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsVertexCache_triggered() -{ - g_Config.bVertexCache = !g_Config.bVertexCache; - UpdateMenus(); -} - -void MainWindow::on_actionFrameskip_triggered() -{ - g_Config.iFrameSkip = !g_Config.iFrameSkip; - UpdateMenus(); -} - -void MainWindow::on_action_Sound_triggered() -{ - g_Config.bEnableSound = !g_Config.bEnableSound; - UpdateMenus(); -} - -void MainWindow::on_action_OptionsFullScreen_triggered() +void MainWindow::fullscrAct() { if(isFullScreen()) { g_Config.bFullScreen = false; + menuBar()->show(); + updateMenus(); + showNormal(); - ui->menubar->setVisible(true); - ui->statusbar->setVisible(true); SetZoom(g_Config.iInternalResolution); InitPadLayout(); if (globalUIState == UISTATE_INGAME && QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); - } else { g_Config.bFullScreen = true; - ui->menubar->setVisible(false); - ui->statusbar->setVisible(false); + menuBar()->hide(); - // Remove constraint - emugl->setMinimumSize(0, 0); - emugl->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - ui->centralwidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + emugl->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); showFullScreen(); - int width = (int) QApplication::desktop()->screenGeometry().width(); - int height = (int) QApplication::desktop()->screenGeometry().height(); - PSP_CoreParameter().pixelWidth = width; - PSP_CoreParameter().pixelHeight = height; - PSP_CoreParameter().outputWidth = width; - PSP_CoreParameter().outputHeight = height; - PSP_CoreParameter().renderWidth = width; - PSP_CoreParameter().renderHeight = height; - - pixel_xres = width; - pixel_yres = height; - dp_xres = pixel_xres; - dp_yres = pixel_yres; if (gpu) gpu->Resized(); InitPadLayout(); @@ -592,139 +362,26 @@ void MainWindow::on_action_OptionsFullScreen_triggered() } } -void MainWindow::on_action_OptionsShowDebugStatistics_triggered() -{ - g_Config.bShowDebugStats = !g_Config.bShowDebugStats; - UpdateMenus(); -} - -void MainWindow::on_action_Show_FPS_counter_triggered() -{ - g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter; - UpdateMenus(); -} - -void setDefLogLevel(LogTypes::LOG_LEVELS level) -{ - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - { - LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; - if(type == LogTypes::G3D || type == LogTypes::HLE) continue; - LogManager::GetInstance()->SetLogLevel(type, level); - } -} - -void MainWindow::on_actionLogDefDebug_triggered() -{ - setDefLogLevel(LogTypes::LDEBUG); - UpdateMenus(); -} - -void MainWindow::on_actionLogDefWarning_triggered() -{ - setDefLogLevel(LogTypes::LWARNING); - UpdateMenus(); -} - -void MainWindow::on_actionLogDefInfo_triggered() -{ - setDefLogLevel(LogTypes::LINFO); - UpdateMenus(); -} - -void MainWindow::on_actionLogDefError_triggered() -{ - setDefLogLevel(LogTypes::LERROR); - UpdateMenus(); -} - -void MainWindow::on_actionLogG3DDebug_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LDEBUG); - UpdateMenus(); -} - -void MainWindow::on_actionLogG3DWarning_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LWARNING); - UpdateMenus(); -} - -void MainWindow::on_actionLogG3DError_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); - UpdateMenus(); -} - -void MainWindow::on_actionLogG3DInfo_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LINFO); - UpdateMenus(); -} - -void MainWindow::on_actionLogHLEDebug_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::HLE, LogTypes::LDEBUG); - UpdateMenus(); -} - -void MainWindow::on_actionLogHLEWarning_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::HLE, LogTypes::LWARNING); - UpdateMenus(); -} - -void MainWindow::on_actionLogHLEInfo_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::HLE, LogTypes::LINFO); - UpdateMenus(); -} - -void MainWindow::on_actionLogHLEError_triggered() -{ - LogManager::GetInstance()->SetLogLevel(LogTypes::HLE, LogTypes::LERROR); - UpdateMenus(); -} - -void MainWindow::on_action_HelpOpenWebsite_triggered() +void MainWindow::websiteAct() { QDesktopServices::openUrl(QUrl("http://www.ppsspp.org/")); } -void MainWindow::on_action_HelpAbout_triggered() +void MainWindow::aboutAct() { - // TODO display about -} - -void MainWindow::on_language_changed(QAction *action) -{ - loadLanguage(action->data().toString()); + QMessageBox::about(this, "PPSSPP Qt", QString::fromUtf8("Created by Henrik Rydg\xc3\xa5rd")); } /* Private functions */ -void MainWindow::SetZoom(float zoom) { - if (zoom < 5) - g_Config.iInternalResolution = (int) zoom; - - pixel_xres = 480 * zoom; - pixel_yres = 272 * zoom; - dp_xres = pixel_xres; - dp_yres = pixel_yres; - - emugl->resize(pixel_xres, pixel_yres); - emugl->setMinimumSize(pixel_xres, pixel_yres); - emugl->setMaximumSize(pixel_xres, pixel_yres); - - ui->centralwidget->setFixedSize(pixel_xres, pixel_yres); - ui->centralwidget->resize(pixel_xres, pixel_yres); +void MainWindow::SetZoom(int zoom) { + if (isFullScreen()) + fullscrAct(); + if (zoom < 1) zoom = 1; + if (zoom > 4) zoom = 4; + g_Config.iInternalResolution = zoom; + emugl->setFixedSize(480 * zoom, 272 * zoom); setFixedSize(sizeHint()); - resize(sizeHint()); - - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; - PSP_CoreParameter().outputWidth = pixel_xres; - PSP_CoreParameter().outputHeight = pixel_yres; if (gpu) gpu->Resized(); @@ -739,67 +396,195 @@ void MainWindow::SetGameTitle(QString text) setWindowTitle(title); } -void switchTranslator(QTranslator &translator, const QString &filename) -{ - qApp->removeTranslator(&translator); - - if (translator.load(filename)) - qApp->installTranslator(&translator); -} - -void MainWindow::loadLanguage(const QString& language) +void MainWindow::loadLanguage(const QString& language, bool translate) { if (currentLanguage != language) { currentLanguage = language; QLocale::setDefault(QLocale(currentLanguage)); - switchTranslator(translator, QString(":/languages/ppsspp_%1.qm").arg(language)); + QApplication::removeTranslator(&translator); + if (translator.load(QString(":/languages/ppsspp_%1.qm").arg(language))) { + QApplication::installTranslator(&translator); + if (translate) + emit retranslate(); + } } } -void MainWindow::createLanguageMenu() +void MainWindow::createMenus() { - QActionGroup *langGroup = new QActionGroup(ui->menuLanguage); - langGroup->setExclusive(true); + // File + MenuTree* fileMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&File")); + fileMenu->add(new MenuAction(this, SLOT(openAct()), QT_TR_NOOP("&Open..."), QKeySequence::Open)) + ->addEnableState(UISTATE_MENU); + fileMenu->add(new MenuAction(this, SLOT(closeAct()), QT_TR_NOOP("&Close"), QKeySequence::Close)) + ->addDisableState(UISTATE_MENU); + fileMenu->addSeparator(); + fileMenu->add(new MenuAction(this, SLOT(qlstateAct()), QT_TR_NOOP("Quickload State"), Qt::Key_F4)) + ->addDisableState(UISTATE_MENU); + fileMenu->add(new MenuAction(this, SLOT(qsstateAct()), QT_TR_NOOP("Quicksave State"), Qt::Key_F2)) + ->addDisableState(UISTATE_MENU); + fileMenu->add(new MenuAction(this, SLOT(lstateAct()), QT_TR_NOOP("&Load State File..."))) + ->addDisableState(UISTATE_MENU); + fileMenu->add(new MenuAction(this, SLOT(sstateAct()), QT_TR_NOOP("&Save State File..."))) + ->addDisableState(UISTATE_MENU); + fileMenu->addSeparator(); + fileMenu->add(new MenuAction(this, SLOT(exitAct()), QT_TR_NOOP("E&xit"), QKeySequence::Quit)); - connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(on_language_changed(QAction *))); + // Emulation + MenuTree* emuMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Emulation")); + emuMenu->add(new MenuAction(this, SLOT(runAct()), QT_TR_NOOP("&Run"), Qt::Key_F7)) + ->addEnableStepping()->addEnableState(UISTATE_PAUSEMENU); + emuMenu->add(new MenuAction(this, SLOT(pauseAct()), QT_TR_NOOP("&Pause"), Qt::Key_F8)) + ->addEnableState(UISTATE_INGAME); + emuMenu->add(new MenuAction(this, SLOT(resetAct()), QT_TR_NOOP("Re&set"))) + ->addEnableState(UISTATE_INGAME); + emuMenu->addSeparator(); + emuMenu->add(new MenuAction(this, SLOT(runonloadAct()), QT_TR_NOOP("Run on &load"))) + ->addEventChecked(&g_Config.bAutoRun); + // Debug + MenuTree* debugMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("De&bug")); + debugMenu->add(new MenuAction(this, SLOT(lmapAct()), QT_TR_NOOP("Load Map File..."))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(smapAct()), QT_TR_NOOP("Save Map File..."))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(resetTableAct()),QT_TR_NOOP("Reset Symbol Table"))) + ->addDisableState(UISTATE_MENU); + debugMenu->addSeparator(); + debugMenu->add(new MenuAction(this, SLOT(dumpNextAct()), QT_TR_NOOP("Dump next frame to log"))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(takeScreen()), QT_TR_NOOP("Take Screenshot"), Qt::Key_F12)) + ->addDisableState(UISTATE_MENU); + debugMenu->addSeparator(); + debugMenu->add(new MenuAction(this, SLOT(disasmAct()), QT_TR_NOOP("Disassembly"), Qt::CTRL + Qt::Key_D)) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(dpyListAct()), QT_TR_NOOP("Display List..."))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(consoleAct()), QT_TR_NOOP("Log Console"))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(memviewAct()), QT_TR_NOOP("Memory View"))) + ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(memviewTexAct()),QT_TR_NOOP("Memory View Texture"))) + ->addDisableState(UISTATE_MENU); + + // Options + MenuTree* optionsMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Options")); + // - Core + MenuTree* coreMenu = new MenuTree(this, optionsMenu, QT_TR_NOOP("&Core")); + coreMenu->add(new MenuAction(this, SLOT(dynarecAct()), QT_TR_NOOP("&CPU Dynarec"))) + ->addEventChecked(&g_Config.bJit); + coreMenu->add(new MenuAction(this, SLOT(vertexDynarecAct()), QT_TR_NOOP("&Vertex Decoder Dynarec"))) + ->addEventChecked(&g_Config.bVertexDecoderJit); + coreMenu->add(new MenuAction(this, SLOT(fastmemAct()), QT_TR_NOOP("Fast &Memory (unstable)"))) + ->addEventChecked(&g_Config.bFastMemory); + coreMenu->add(new MenuAction(this, SLOT(ignoreIllegalAct()), QT_TR_NOOP("&Ignore Illegal reads/writes"))) + ->addEventChecked(&g_Config.bIgnoreBadMemAccess); + // - Video + MenuTree* videoMenu = new MenuTree(this, optionsMenu, QT_TR_NOOP("&Video")); + // - Anisotropic Filtering + MenuTree* anisotropicMenu = new MenuTree(this, videoMenu, QT_TR_NOOP("&Anisotropic Filtering")); + anisotropicGroup = new MenuActionGroup(this, anisotropicMenu, SLOT(anisotropicGroup_triggered(QAction *)), + QStringList() << "Off" << "2x" << "4x" << "8x" << "16x", + QList() << 0 << 1 << 2 << 3 << 4); + // TODO: Check for newer buffer render options + videoMenu->add(new MenuAction(this, SLOT(bufferRenderAct()), QT_TR_NOOP("&Buffered Rendering"), Qt::Key_F5)) + ->addEventChecked(&g_Config.iRenderingMode); + videoMenu->add(new MenuAction(this, SLOT(linearAct()), QT_TR_NOOP("&Linear Filtering"))) + ->addEventChecked(&g_Config.iTexFiltering); + videoMenu->addSeparator(); + // - Screen Size + MenuTree* screenMenu = new MenuTree(this, videoMenu, QT_TR_NOOP("&Screen Size")); + screenGroup = new MenuActionGroup(this, screenMenu, SLOT(screenGroup_triggered(QAction *)), + QStringList() << "1x" << "2x" << "3x" << "4x", + QList() << 1 << 2 << 3 << 4, + QList() << Qt::CTRL + Qt::Key_1 << Qt::CTRL + Qt::Key_2 << Qt::CTRL + Qt::Key_3 << Qt::CTRL + Qt::Key_4); + + videoMenu->add(new MenuAction(this, SLOT(stretchAct()), QT_TR_NOOP("&Stretch to Display"))) + ->addEventChecked(&g_Config.bStretchToDisplay); + videoMenu->addSeparator(); + videoMenu->add(new MenuAction(this, SLOT(transformAct()), QT_TR_NOOP("&Hardware Transform"), Qt::Key_F6)) + ->addEventChecked(&g_Config.bHardwareTransform); + videoMenu->add(new MenuAction(this, SLOT(vertexCacheAct()), QT_TR_NOOP("&Vertex Cache"))) + ->addEventChecked(&g_Config.bVertexCache); + videoMenu->add(new MenuAction(this, SLOT(frameskipAct()), QT_TR_NOOP("&Frameskip"))) + ->addEventChecked(&g_Config.iFrameSkip); + optionsMenu->add(new MenuAction(this, SLOT(audioAct()), QT_TR_NOOP("&Audio"))) + ->addEventChecked(&g_Config.bEnableSound); + optionsMenu->addSeparator(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + optionsMenu->add(new MenuAction(this, SLOT(fullscrAct()), QT_TR_NOOP("&Fullscreen"), Qt::Key_F11)) +#else + optionsMenu->add(new MenuAction(this, SLOT(fullscrAct()), QT_TR_NOOP("&Fullscreen"), QKeySequence::FullScreen)) +#endif + ->addEventChecked(&g_Config.bFullScreen); + optionsMenu->add(new MenuAction(this, SLOT(statsAct()), QT_TR_NOOP("&Show debug statistics"))) + ->addEventChecked(&g_Config.bShowDebugStats); + optionsMenu->add(new MenuAction(this, SLOT(showFPSAct()), QT_TR_NOOP("&Show FPS"))) + ->addEventChecked(&g_Config.iShowFPSCounter); + optionsMenu->addSeparator(); + // - Log Levels + MenuTree* levelsMenu = new MenuTree(this, optionsMenu, QT_TR_NOOP("Lo&g levels")); + QMenu* defaultLogMenu = levelsMenu->addMenu("Default"); + defaultLogGroup = new MenuActionGroup(this, defaultLogMenu, SLOT(defaultLogGroup_triggered(QAction *)), + QStringList() << "Debug" << "Warning" << "Info" << "Error", + QList() << LogTypes::LDEBUG << LogTypes::LWARNING << LogTypes::LINFO << LogTypes::LERROR); + QMenu* g3dLogMenu = levelsMenu->addMenu("G3D"); + g3dLogGroup = new MenuActionGroup(this, g3dLogMenu, SLOT(g3dLogGroup_triggered(QAction *)), + QStringList() << "Debug" << "Warning" << "Info" << "Error", + QList() << LogTypes::LDEBUG << LogTypes::LWARNING << LogTypes::LINFO << LogTypes::LERROR); + QMenu* hleLogMenu = levelsMenu->addMenu("HLE"); + hleLogGroup = new MenuActionGroup(this, hleLogMenu, SLOT(hleLogGroup_triggered(QAction *)), + QStringList() << "Debug" << "Warning" << "Info" << "Error", + QList() << LogTypes::LDEBUG << LogTypes::LWARNING << LogTypes::LINFO << LogTypes::LERROR); + optionsMenu->addSeparator(); + // - Language + MenuTree* langMenu = new MenuTree(this, optionsMenu, QT_TR_NOOP("&Language")); + QActionGroup* langGroup = new QActionGroup(this); QStringList fileNames = QDir(":/languages").entryList(QStringList("ppsspp_*.qm")); if (fileNames.size() == 0) { - QAction *action = new QAction(tr("No translations"), this); - action->setCheckable(false); + QAction *action = new QAction("No translations", this); action->setDisabled(true); - ui->menuLanguage->addAction(action); langGroup->addAction(action); - } - - for (int i = 0; i < fileNames.size(); ++i) - { - QString locale = fileNames[i]; - locale.truncate(locale.lastIndexOf('.')); - locale.remove(0, locale.indexOf('_') + 1); - -#if QT_VERSION >= 0x040800 - QString language = QLocale(locale).nativeLanguageName(); -#else - QString language = QLocale::languageToString(QLocale(locale).language()); -#endif - QAction *action = new QAction(language, this); - action->setCheckable(true); - action->setData(locale); - - ui->menuLanguage->addAction(action); - langGroup->addAction(action); - - // TODO check en as default until we save language to config - if ("en" == locale) + } else { + connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(langChanged(QAction *))); + bool found = false; + QString currentLocale = g_Config.sLanguageIni.c_str(); + QString currentLang = currentLocale.split('_').first(); + for (int i = 0; i < fileNames.size(); ++i) { - action->setChecked(true); - currentLanguage = "en"; + QString locale = fileNames[i]; + locale.truncate(locale.lastIndexOf('.')); + locale.remove(0, locale.indexOf('_') + 1); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) + QString language = QLocale(locale).nativeLanguageName(); +#else + QString language = QLocale::languageToString(QLocale(locale).language()); +#endif + QAction *action = new MenuAction(this, langGroup, locale, language); + std::string testLang = g_Config.sLanguageIni; + if (currentLocale == locale || currentLang == locale) { + action->setChecked(true); + loadLanguage(locale, false); + found = true; + } + + if (!found && locale == "en") { + action->setChecked(true); + } } } + langMenu->addActions(langGroup->actions()); + + // Help + MenuTree* helpMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Help")); + helpMenu->add(new MenuAction(this, SLOT(websiteAct()), QT_TR_NOOP("&Go to official website"), QKeySequence::HelpContents)); + helpMenu->add(new MenuAction(this, SLOT(aboutAct()), QT_TR_NOOP("&About PPSSPP..."), QKeySequence::WhatsThis)); + + retranslate(); } void MainWindow::notifyMapsLoaded() diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 17c775397b..69d7a9af61 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -1,28 +1,32 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include +#include #include -#include -#include +#include + +#include "ConsoleListener.h" #include "Core/Core.h" -#include "input/input_state.h" +#include "Core/Config.h" #include "debugger_disasm.h" #include "debugger_memory.h" #include "debugger_memorytex.h" #include "debugger_displaylist.h" +#include "base/QtMain.h" -class QtEmuGL; -namespace Ui { -class MainWindow; -} +extern bool g_TakeScreenshot; + +class MenuAction; +class MenuTree; class MainWindow : public QMainWindow { - Q_OBJECT - + Q_OBJECT + public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); + explicit MainWindow(QWidget *parent = 0); + ~MainWindow() { }; Debugger_Disasm* GetDialogDisasm() { return dialogDisasm; } Debugger_Memory* GetDialogMemory() { return memoryWindow; } @@ -31,117 +35,105 @@ public: CoreState GetNextState() { return nextState; } void ShowMemory(u32 addr); - void UpdateMenus(); + void updateMenus(); protected: - void changeEvent(QEvent *e); - void closeEvent(QCloseEvent *); - void keyPressEvent(QKeyEvent *e); - void keyReleaseEvent(QKeyEvent *e); + void closeEvent(QCloseEvent *) { exitAct(); } + +signals: + void retranslate(); + void updateMenu(); public slots: void Boot(); - void CoreEmitWait(bool); - void Update(); + void newFrame(); private slots: // File - void on_action_FileLoad_triggered(); - void on_action_FileClose_triggered(); - void on_action_FileQuickloadState_triggered(); - void on_action_FileQuickSaveState_triggered(); - void on_action_FileLoadStateFile_triggered(); - void on_action_FileSaveStateFile_triggered(); - void on_action_FileExit_triggered(); + void openAct(); + void closeAct(); + void qlstateAct(); + void qsstateAct(); + void lstateAct(); + void sstateAct(); + void exitAct(); // Emulation - void on_action_EmulationRun_triggered(); - void on_action_EmulationPause_triggered(); - void on_action_EmulationReset_triggered(); - void on_action_EmulationRunLoad_triggered(); + void runAct(); + void pauseAct(); + void resetAct(); + void runonloadAct(); // Debug - void on_action_DebugLoadMapFile_triggered(); - void on_action_DebugSaveMapFile_triggered(); - void on_action_DebugResetSymbolTable_triggered(); - void on_action_DebugDumpFrame_triggered(); - void on_action_DebugDisassembly_triggered(); - void on_action_DebugDisplayList_triggered(); - void on_action_DebugLog_triggered(); - void on_action_DebugMemoryView_triggered(); - void on_action_DebugMemoryViewTexture_triggered(); + void lmapAct(); + void smapAct(); + void resetTableAct(); + void dumpNextAct(); + void takeScreen() { g_TakeScreenshot = true; } + void disasmAct(); + void dpyListAct(); + void consoleAct(); + void memviewAct(); + void memviewTexAct(); // Options // Core - void on_action_CPUDynarec_triggered(); - void on_action_CPUInterpreter_triggered(); - void on_action_OptionsFastMemory_triggered(); - void on_action_OptionsIgnoreIllegalReadsWrites_triggered(); + void dynarecAct() { g_Config.bJit = !g_Config.bJit; } + void vertexDynarecAct() { g_Config.bVertexDecoderJit = !g_Config.bVertexDecoderJit; } + void fastmemAct() { g_Config.bFastMemory = !g_Config.bFastMemory; } + void ignoreIllegalAct() { g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess; } // Video - void on_action_AFOff_triggered(); - void on_action_AF2x_triggered(); - void on_action_AF4x_triggered(); - void on_action_AF8x_triggered(); - void on_action_AF16x_triggered(); + void anisotropicGroup_triggered(QAction *action) { g_Config.iAnisotropyLevel = action->data().toInt(); } - void on_action_OptionsBufferedRendering_triggered(); - void on_action_OptionsLinearFiltering_triggered(); + void bufferRenderAct() { g_Config.iRenderingMode = !g_Config.iRenderingMode; } + void linearAct() { g_Config.iTexFiltering = (g_Config.iTexFiltering != 0) ? 0 : 3; } - void on_action_OptionsScreen1x_triggered(); - void on_action_OptionsScreen2x_triggered(); - void on_action_OptionsScreen3x_triggered(); - void on_action_OptionsScreen4x_triggered(); + void screenGroup_triggered(QAction *action) { SetZoom(action->data().toInt()); } - void on_action_Stretch_to_display_triggered(); - void on_action_OptionsHardwareTransform_triggered(); - void on_action_OptionsVertexCache_triggered(); - void on_actionFrameskip_triggered(); + void stretchAct(); + void transformAct() { g_Config.bHardwareTransform = !g_Config.bHardwareTransform; } + void vertexCacheAct() { g_Config.bVertexCache = !g_Config.bVertexCache; } + void frameskipAct() { g_Config.iFrameSkip = !g_Config.iFrameSkip; } // Sound - void on_action_Sound_triggered(); + void audioAct() { g_Config.bEnableSound = !g_Config.bEnableSound; } - void on_action_OptionsFullScreen_triggered(); - void on_action_OptionsShowDebugStatistics_triggered(); - void on_action_Show_FPS_counter_triggered(); + void fullscrAct(); + void statsAct() { g_Config.bShowDebugStats = !g_Config.bShowDebugStats; } + void showFPSAct() { g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter; } // Logs - void on_actionLogDefDebug_triggered(); - void on_actionLogDefWarning_triggered(); - void on_actionLogDefInfo_triggered(); - void on_actionLogDefError_triggered(); - - void on_actionLogG3DDebug_triggered(); - void on_actionLogG3DWarning_triggered(); - void on_actionLogG3DError_triggered(); - void on_actionLogG3DInfo_triggered(); - - void on_actionLogHLEDebug_triggered(); - void on_actionLogHLEWarning_triggered(); - void on_actionLogHLEInfo_triggered(); - void on_actionLogHLEError_triggered(); + void defaultLogGroup_triggered(QAction * action) { + LogTypes::LOG_LEVELS level = (LogTypes::LOG_LEVELS)action->data().toInt(); + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) + { + LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; + if(type == LogTypes::G3D || type == LogTypes::HLE) + continue; + LogManager::GetInstance()->SetLogLevel(type, level); + } + } + void g3dLogGroup_triggered(QAction * action) { LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, (LogTypes::LOG_LEVELS)action->data().toInt()); } + void hleLogGroup_triggered(QAction * action) { LogManager::GetInstance()->SetLogLevel(LogTypes::HLE, (LogTypes::LOG_LEVELS)action->data().toInt()); } // Help - void on_action_HelpOpenWebsite_triggered(); - void on_action_HelpAbout_triggered(); + void websiteAct(); + void aboutAct(); // Others - void on_language_changed(QAction *action); + void langChanged(QAction *action) { loadLanguage(action->data().toString(), true); } private: - void SetZoom(float zoom); + void SetZoom(int zoom); void SetGameTitle(QString text); - void loadLanguage(const QString &language); - void createLanguageMenu(); + void loadLanguage(const QString &language, bool retranslate); + void createMenus(); void notifyMapsLoaded(); QTranslator translator; QString currentLanguage; - Ui::MainWindow *ui; - - QtEmuGL *emugl; - QTimer timer; CoreState nextState; InputState input_state; GlobalUIState lastUIState; @@ -150,6 +142,128 @@ private: Debugger_Memory *memoryWindow; Debugger_MemoryTex *memoryTexWindow; Debugger_DisplayList *displaylistWindow; + + QActionGroup *anisotropicGroup, *screenGroup, + *defaultLogGroup, *g3dLogGroup, *hleLogGroup; +}; + +class MenuAction : public QAction +{ + Q_OBJECT + +public: + // Add to QMenu + MenuAction(QWidget* parent, const char* callback, char* text, QKeySequence key = 0) : + QAction(parent), _text(text), _eventCheck(0), _stateEnable(-1), _stateDisable(-1), _enableStepping(false) + { + if (key != (QKeySequence)0) { + this->setShortcut(key); + parent->addAction(this); // So we don't lose the shortcut when menubar is hidden + } + connect(this, SIGNAL(triggered()), parent, callback); + connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate())); + connect(parent, SIGNAL(updateMenu()), this, SLOT(update())); + } + // Add to QActionGroup + MenuAction(QWidget* parent, QActionGroup* group, QVariant data, QString text, QKeySequence key = 0) : + QAction(parent), _eventCheck(0), _stateEnable(-1), _stateDisable(-1), _enableStepping(false) + { + this->setCheckable(true); + this->setData(data); + this->setText(text); // Not translatable, yet + if (key != (QKeySequence)0) { + this->setShortcut(key); + parent->addAction(this); // So we don't lose the shortcut when menubar is hidden + } + group->addAction(this); + } + // Event which causes it to be checked + void addEventChecked(bool* event) { + this->setCheckable(true); + _eventCheck = event; + } + // TODO: Possibly handle compares + void addEventChecked(int* event) { + this->setCheckable(true); + _eventCheck = (bool*)event; + } + // UI State which causes it to be enabled + void addEnableState(int state) { + _stateEnable = state; + } + void addDisableState(int state) { + _stateDisable = state; + } + MenuAction* addEnableStepping() { + _enableStepping = true; + return this; + } +public slots: + void retranslate() { + setText(qApp->translate("MainWindow", _text)); + } + void update() { + if (_eventCheck) + setChecked(*_eventCheck); + if (_stateEnable >= 0) + setEnabled(globalUIState == _stateEnable); + if (_stateDisable >= 0) + setEnabled(globalUIState != _stateDisable); + if (_enableStepping && Core_IsStepping()) + setEnabled(true); + } +private: + char* _text; + bool* _eventCheck; + int _stateEnable, _stateDisable; + bool _enableStepping; +}; + +class MenuActionGroup : public QActionGroup +{ + Q_OBJECT +public: + MenuActionGroup(QWidget* parent, QMenu* menu, const char* callback, QStringList nameList, + QList valueList, QList keyList = QList()) : + QActionGroup(parent) + { + QListIterator i(valueList); + QListIterator k(keyList); + foreach(QString name, nameList) { + new MenuAction(parent, this, i.next(), name, k.next()); + } + connect(this, SIGNAL(triggered(QAction *)), parent, callback); + menu->addActions(this->actions()); + } +}; + +class MenuTree : public QMenu +{ + Q_OBJECT +public: + MenuTree(QWidget* parent, QMenuBar* menu, char* text) : + QMenu(parent), _text(text) + { + menu->addMenu(this); + connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate())); + } + MenuTree(QWidget* parent, QMenu* menu, char* text) : + QMenu(parent), _text(text) + { + menu->addMenu(this); + connect(parent, SIGNAL(retranslate()), this, SLOT(retranslate())); + } + MenuAction* add(MenuAction* action) + { + addAction(action); + return action; + } +public slots: + void retranslate() { + setTitle(qApp->translate("MainWindow", _text)); + } +private: + char* _text; }; #endif // MAINWINDOW_H diff --git a/Qt/mainwindow.ui b/Qt/mainwindow.ui deleted file mode 100644 index 5585bd8c00..0000000000 --- a/Qt/mainwindow.ui +++ /dev/null @@ -1,674 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - - 0 - 0 - - - - PPSSPP - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - 0 - 0 - 800 - 21 - - - - - &File - - - - - - - - - - - - - - &Emulation - - - - - - - - - - - Debu&g - - - - - - - - - - - - - - - - &Options - - - - Lo&g Levels - - - - G3D - - - - - - - - - HLE - - - - - - - - - Default - - - - - - - - - - - - - - &Language - - - - - &Video - - - - &Anisotropic filtering - - - - - - - - - - &Zoom - - - - - - - - - - - - - - - - - - - - &Core - - - - - - - - - - - - - - - - - - - - - - - &Help - - - - - - - - - - - - - - - &Open... - - - - - &Close - - - - - - - - - - - Quickload state - - - F4 - - - - - Quicksave state - - - F2 - - - - - &Load State File... - - - - - &Save State File... - - - - - E&xit - - - - - &Run - - - F7 - - - - - &Pause - - - F8 - - - - - R&eset - - - - - true - - - &Interpreter - - - - - true - - - &Dynarec - - - - - false - - - Load &Map File... - - - - - false - - - &Save Map File... - - - - - false - - - &Reset Symbol Table - - - - - &Disassembly - - - Ctrl+D - - - - - false - - - &Log Console - - - Ctrl+L - - - - - Memory &View... - - - Ctrl+M - - - - - &Toggle fullscreen - - - F11 - - - - - true - - - &Buffered Rendering - - - F5 - - - - - true - - - &Hardware Transform - - - F6 - - - - - true - - - &Linear Filtering - - - - - true - - - Show &debug statistics - - - - - true - - - Screen &1x - - - Ctrl+1 - - - - - true - - - Screen &2x - - - Ctrl+2 - - - - - true - - - Screen &3x - - - Ctrl+3 - - - - - true - - - Screen &4x - - - Ctrl+4 - - - - - true - - - &Fast Memory (dynarec, unstable) - - - - - true - - - I&gnore illegal reads/writes - - - - - &Go to http://www.ppsspp.org/ - - - - - &About PPSSPP... - - - - - true - - - Debug - - - - - true - - - Warning - - - - - true - - - Error - - - - - true - - - Info - - - - - true - - - Debug - - - - - true - - - Warning - - - - - true - - - Info - - - - - true - - - Error - - - - - true - - - Debug - - - - - true - - - Warning - - - - - true - - - Info - - - - - true - - - Error - - - - - Run on loa&d - - - - - D&ump next frame to log - - - - - true - - - &Vertex Cache - - - - - Memory View Texture... - - - - - DisplayList... - - - - - true - - - Off - - - - - true - - - 2x - - - - - true - - - 4x - - - - - true - - - 8x - - - - - true - - - 16x - - - - - true - - - Show &FPS counter - - - - - true - - - S&tretch to display - - - - - true - - - &Sound emulation - - - - - true - - - Frameskip - - - - - - QtEmuGL - QWidget -
qtemugl.h
- 1 -
-
- - -
diff --git a/Qt/qkeyedit.cpp b/Qt/qkeyedit.cpp deleted file mode 100644 index b01f0863ef..0000000000 --- a/Qt/qkeyedit.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "qkeyedit.h" -#include -#include - -QKeyEdit::QKeyEdit(QWidget *parent) : - QLineEdit(parent) -{ -} - -bool QKeyEdit::event(QEvent *e) -{ - if(e->type() == QEvent::KeyPress) - { - QKeyEvent *ke = static_cast(e); - QKeySequence seq(ke->key()); - setText(seq.toString()); - return true; - } - - return QLineEdit::event(e); -} diff --git a/Qt/qkeyedit.h b/Qt/qkeyedit.h deleted file mode 100644 index 1beb9ac352..0000000000 --- a/Qt/qkeyedit.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef QKEYEDIT_H -#define QKEYEDIT_H - -#include - -class QKeyEdit : public QLineEdit -{ - Q_OBJECT -public: - explicit QKeyEdit(QWidget *parent = 0); - -protected: - bool event(QEvent *e); -signals: - -public slots: - -}; - -#endif // QKEYEDIT_H diff --git a/Qt/qtemugl.cpp b/Qt/qtemugl.cpp deleted file mode 100644 index 3c3a9683e2..0000000000 --- a/Qt/qtemugl.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "qtemugl.h" - -#include - -#include "base/display.h" -#include "base/timeutil.h" -#include "Core/Config.h" - -QtEmuGL::QtEmuGL(QWidget *parent) : - QGLWidget(parent) -{ -} - -void QtEmuGL::init(InputState *inputState) -{ - input_state = inputState; -} - -void QtEmuGL::initializeGL() -{ -#ifndef USING_GLES2 - glewInit(); -#endif - NativeInitGraphics(); -} -void QtEmuGL::paintGL() -{ - static double startTime = 0; - NativeUpdate(*input_state); - NativeRender(); - EndInputState(input_state); - - if (globalUIState != UISTATE_INGAME && globalUIState != UISTATE_EXIT) { - time_update(); - double diffTime = time_now_d() - startTime; - startTime = time_now_d(); - int sleepTime = (int) (1000000.0 / 60.0) - (int) (diffTime * 1000000.0); - if (sleepTime > 0) - usleep(sleepTime); - } -} - -void QtEmuGL::mouseDoubleClickEvent(QMouseEvent *) -{ - if (!g_Config.bShowTouchControls || globalUIState != UISTATE_INGAME) - emit doubleClick(); -} - -void QtEmuGL::mousePressEvent(QMouseEvent *e) -{ - TouchInput input; - input_state->pointer_down[0] = true; - input_state->pointer_x[0] = e->x(); - input_state->pointer_y[0] = e->y(); - - input.x = e->x(); - input.y = e->y(); - input.flags = TOUCH_DOWN; - input.id = 0; - NativeTouch(input); -} - -void QtEmuGL::mouseReleaseEvent(QMouseEvent *e) -{ - TouchInput input; - input_state->pointer_down[0] = false; - - input.x = e->x(); - input.y = e->y(); - input.flags = TOUCH_UP; - input.id = 0; - NativeTouch(input); -} - -void QtEmuGL::mouseMoveEvent(QMouseEvent *e) -{ - TouchInput input; - input.x = e->x(); - input.y = e->y(); - input.flags = TOUCH_MOVE; - input.id = 0; - NativeTouch(input); -} - -void QtEmuGL::wheelEvent(QWheelEvent *e) -{ - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = e->delta()<0 ? NKCODE_EXT_MOUSEWHEEL_DOWN : NKCODE_EXT_MOUSEWHEEL_UP; - key.flags = KEY_DOWN; - NativeKey(key); -} diff --git a/Qt/qtemugl.h b/Qt/qtemugl.h deleted file mode 100644 index fede4a1459..0000000000 --- a/Qt/qtemugl.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef QTEMUGL_H -#define QTEMUGL_H - -#include "gfx_es2/glsl_program.h" -#include "input/input_state.h" -#include -#include "QtHost.h" - -class QtEmuGL : public QGLWidget -{ - Q_OBJECT -public: - explicit QtEmuGL(QWidget *parent = nullptr); - ~QtEmuGL() { - NativeShutdownGraphics(); - } - - void init(InputState* inputState); -signals: - void doubleClick(); -protected: - void initializeGL(); - void paintGL(); - void mouseDoubleClickEvent(QMouseEvent *); - void mousePressEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void wheelEvent(QWheelEvent *e); - -private: - InputState *input_state; -}; - -#endif // QTEMUGL_H diff --git a/Qt/resources.qrc b/Qt/resources.qrc deleted file mode 100644 index 0385010eed..0000000000 --- a/Qt/resources.qrc +++ /dev/null @@ -1,31 +0,0 @@ - - - resources/psp.png - resources/psp_map.png - resources/psp_rightbtn_red.png - resources/psp_smallbtn_red.png - resources/psp_down_red.png - resources/psp_up_red.png - resources/psp_right_red.png - resources/psp_left_red.png - resources/psp_rt_red.png - resources/psp_lt_red.png - resources/psp_aright.png - resources/psp_adown.png - resources/psp_aleft.png - resources/psp_aup.png - resources/stop1.ico - resources/icon1.ico - - - languages/ppsspp_cn.qm - languages/ppsspp_en.qm - languages/ppsspp_fr.qm - languages/ppsspp_pl.qm - languages/ppsspp_de.qm - languages/ppsspp_tc.qm - languages/ppsspp_pt-br.qm - languages/ppsspp_id.qm - languages/ppsspp_ru.qm - - diff --git a/Qt/resources/icon1.ico b/Qt/resources/breakpoint.ico similarity index 100% rename from Qt/resources/icon1.ico rename to Qt/resources/breakpoint.ico diff --git a/Qt/resources/stop1.ico b/Qt/resources/breakpointDisable.ico similarity index 100% rename from Qt/resources/stop1.ico rename to Qt/resources/breakpointDisable.ico diff --git a/Qt/resources/psp.png b/Qt/resources/psp.png deleted file mode 100644 index 7de480766b..0000000000 Binary files a/Qt/resources/psp.png and /dev/null differ diff --git a/Qt/resources/psp_adown.png b/Qt/resources/psp_adown.png deleted file mode 100644 index 141664b2a4..0000000000 Binary files a/Qt/resources/psp_adown.png and /dev/null differ diff --git a/Qt/resources/psp_aleft.png b/Qt/resources/psp_aleft.png deleted file mode 100644 index 60545be238..0000000000 Binary files a/Qt/resources/psp_aleft.png and /dev/null differ diff --git a/Qt/resources/psp_aright.png b/Qt/resources/psp_aright.png deleted file mode 100644 index f951c2bb93..0000000000 Binary files a/Qt/resources/psp_aright.png and /dev/null differ diff --git a/Qt/resources/psp_aup.png b/Qt/resources/psp_aup.png deleted file mode 100644 index 8028261674..0000000000 Binary files a/Qt/resources/psp_aup.png and /dev/null differ diff --git a/Qt/resources/psp_down_red.png b/Qt/resources/psp_down_red.png deleted file mode 100644 index 0ec28673b2..0000000000 Binary files a/Qt/resources/psp_down_red.png and /dev/null differ diff --git a/Qt/resources/psp_left_red.png b/Qt/resources/psp_left_red.png deleted file mode 100644 index 353d9be44b..0000000000 Binary files a/Qt/resources/psp_left_red.png and /dev/null differ diff --git a/Qt/resources/psp_lt_red.png b/Qt/resources/psp_lt_red.png deleted file mode 100644 index a44504f1f2..0000000000 Binary files a/Qt/resources/psp_lt_red.png and /dev/null differ diff --git a/Qt/resources/psp_map.png b/Qt/resources/psp_map.png deleted file mode 100644 index f164010885..0000000000 Binary files a/Qt/resources/psp_map.png and /dev/null differ diff --git a/Qt/resources/psp_right_red.png b/Qt/resources/psp_right_red.png deleted file mode 100644 index 81b809e055..0000000000 Binary files a/Qt/resources/psp_right_red.png and /dev/null differ diff --git a/Qt/resources/psp_rightbtn_red.png b/Qt/resources/psp_rightbtn_red.png deleted file mode 100644 index 258822507a..0000000000 Binary files a/Qt/resources/psp_rightbtn_red.png and /dev/null differ diff --git a/Qt/resources/psp_rt_red.png b/Qt/resources/psp_rt_red.png deleted file mode 100644 index ce9b87163c..0000000000 Binary files a/Qt/resources/psp_rt_red.png and /dev/null differ diff --git a/Qt/resources/psp_smallbtn_red.png b/Qt/resources/psp_smallbtn_red.png deleted file mode 100644 index 4239c46fc5..0000000000 Binary files a/Qt/resources/psp_smallbtn_red.png and /dev/null differ diff --git a/Qt/resources/psp_up_red.png b/Qt/resources/psp_up_red.png deleted file mode 100644 index dd6f718a79..0000000000 Binary files a/Qt/resources/psp_up_red.png and /dev/null differ diff --git a/README.md b/README.md index b8b61e8815..3630557c65 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ PPSSPP - a fast and portable PSP emulator ========================================= -Written by Henrik Rydgård +Created by Henrik Rydgård +Additional code by many contributors, see the Credits screen Originally released under the GPL 2.0 (and later) in November 2012 Official website: http://www.ppsspp.org/ +No BIOS file required to play, PPSSPP is in many ways a "HLE" emulator. + To contribute, see [the development page](http://www.ppsspp.org/development.html). For the latest source code, see [our github page](https://github.com/hrydgard/ppsspp). @@ -15,6 +18,22 @@ For the latest source code, see [our github page](https://github.com/hrydgard/pp For build instructions and other development tutorials, see the [wiki](https://github.com/hrydgard/ppsspp/wiki). +What's new in 0.9.6 +------------------- +* Large general speed improvements and assorted bug fixes +* "Software Skinning" option which speeds up many games with animated 3D characters + (but may slow down a few, like Monster Hunter games - experiment with turning it off) +* Various fixes around stencil/alpha, reducing glow problems in Wipeout and Gods Eater Burst. +* Timing improvements making more games run at the correct FPS, also fixing some audio issues +* More debugger features +* Option for four-way touch dpad, avoiding diagonal dpad issues +* Better looking and individually resizable touch controls +* Add ability to switch UMD in multi-disc games (works for most) +* Emulate PSP-2000 rather than the 1000 model by default. Not much different in practice. +* Automatic install of games from ZIP files, like demos and many homebrew. +* VERY basic ad-hoc online play support, to be improved in future versions. See below. +* Software renderer improvements + What's new in 0.9.5 ------------------- * Many, many emulation fixes: @@ -37,3 +56,30 @@ What's new in 0.9.5 * Accurate system information for mobile devices. * Qt audio has been fixed. * Analog controller support for Blackberry. + +ADHOC SUPPORT (by Igor Calabria) +================================ +This is based on coldbird's code: http://code.google.com/p/aemu/ +All credit goes to him! + +Status +------ +Code is a bit of a mess and it's not fully functional yet, I still need to implement +some functions and add a upnp lib(really important for people with routers). + +I did test it with some games(emulator <-> real psp with the server running locally) +and it's looking good: + +* Worms Open Warfare: Ran just fine, I was able to play a whole match without problems +* Monster Hunter Freedom Unite: Runs fine too. Gathering Hall and embarking on quests works +* Dissidia Duodecim 012: Doesn't work. It requires some functions that I haven't implemented +yet. Also, it uses a port < 1000 and thats reserved for admin apps on linux, running the emu +as sudo "solves" it, but it's far from ideal. +* Pacman World Rally: Works too. + +Update (Kyhel) : +--------------- +* Now compiles on both Mac OSX and Windows. For more details on how to play and build +go to see there http://forums.ppsspp.org/showthread.php?tid=3595&pid=59241#pid59241 +* Got it tested windows <-> mac osx <-> psp, it works +* Monster Hunter 3rd HD works too, as well as God Eater Burst. diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp new file mode 100644 index 0000000000..3a83756375 --- /dev/null +++ b/SDL/SDLJoystick.cpp @@ -0,0 +1,130 @@ +#include "SDL/SDLJoystick.h" + +#include + +extern "C" { + int SDLJoystickThreadWrapper(void *SDLJoy){ + SDLJoystick *stick = static_cast(SDLJoy); + stick->runLoop(); + return 0; + } +} + +SDLJoystick::SDLJoystick(bool init_SDL ): running(true),joy(NULL),thread(NULL){ + if (init_SDL) + { + SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO +#ifndef _WIN32 + | SDL_INIT_EVENTTHREAD +#endif + ); + } + fillMapping(); + + int numjoys = SDL_NumJoysticks(); + SDL_JoystickEventState(SDL_ENABLE); + if (numjoys > 0) { + joy = SDL_JoystickOpen(0); + } +} + +SDLJoystick::~SDLJoystick(){ + if (thread) + { + running = false; + SDL_Event evt; + evt.type = SDL_USEREVENT; + SDL_PushEvent(&evt); + SDL_WaitThread(thread,0); + } + SDL_JoystickClose(joy); +} + +void SDLJoystick::startEventLoop(){ + thread = SDL_CreateThread(SDLJoystickThreadWrapper, static_cast(this)); +} + +void SDLJoystick::ProcessInput(SDL_Event &event){ + switch (event.type) { + case SDL_JOYAXISMOTION: + { + AxisInput axis; + axis.axisId = SDLJoyAxisMap[event.jaxis.axis]; + // 1.2 to try to approximate the PSP's clamped rectangular range. + axis.value = 1.2 * event.jaxis.value / 32767.0f; + if (axis.value > 1.0f) axis.value = 1.0f; + if (axis.value < -1.0f) axis.value = -1.0f; + axis.deviceId = DEVICE_ID_PAD_0; + axis.flags = 0; + NativeAxis(axis); + break; + } + + case SDL_JOYBUTTONDOWN: + { + KeyInput key; + key.flags = KEY_DOWN; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_JOYBUTTONUP: + { + KeyInput key; + key.flags = KEY_UP; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_JOYHATMOTION: + { +#ifdef _WIN32 + KeyInput key; + key.deviceId = DEVICE_ID_PAD_0; + + key.flags = (event.jhat.value & SDL_HAT_UP)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_UP; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_LEFT)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_LEFT; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_DOWN)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_DOWN; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_RIGHT)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_RIGHT; + NativeKey(key); +#else + AxisInput axisX; + AxisInput axisY; + axisX.axisId = JOYSTICK_AXIS_HAT_X; + axisY.axisId = JOYSTICK_AXIS_HAT_Y; + axisX.deviceId = DEVICE_ID_PAD_0; + axisY.deviceId = DEVICE_ID_PAD_0; + axisX.value = 0.0f; + axisY.value = 0.0f; + if (event.jhat.value & SDL_HAT_LEFT) axisX.value = -1.0f; + if (event.jhat.value & SDL_HAT_RIGHT) axisX.value = 1.0f; + if (event.jhat.value & SDL_HAT_DOWN) axisY.value = 1.0f; + if (event.jhat.value & SDL_HAT_UP) axisY.value = -1.0f; + NativeAxis(axisX); + NativeAxis(axisY); +#endif + break; + } + } +} + +void SDLJoystick::runLoop(){ + while (running){ + SDL_Event evt; + int res = SDL_WaitEvent(&evt); + if (res){ + ProcessInput(evt); + } + } +} diff --git a/SDL/SDLJoystick.h b/SDL/SDLJoystick.h new file mode 100644 index 0000000000..e4f1dece44 --- /dev/null +++ b/SDL/SDLJoystick.h @@ -0,0 +1,96 @@ +#pragma once + +#ifdef _WIN32 +#include "SDL/SDL.h" +#include "SDL/SDL_joystick.h" +#include "SDL/SDL_thread.h" +#else +#include "SDL.h" +#include "SDL_joystick.h" +#include "SDL_thread.h" +#endif + +#include "input/input_state.h" +#include "input/keycodes.h" +#include "net/resolve.h" +#include "base/NativeApp.h" + +extern "C" { + int SDLJoystickThreadWrapper(void *SDLJoy); +} + +class SDLJoystick{ + friend int ::SDLJoystickThreadWrapper(void *); +public: + SDLJoystick(bool init_SDL = false); + ~SDLJoystick(); + + void startEventLoop(); + void ProcessInput(SDL_Event &event); + +private: + + void runLoop(); + void fillMapping() + { + // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong + // on other controllers. + + //TODO: C++11 aggregate initialization + //would remove runtime overhead completely +#ifdef _WIN32 + SDLJoyButtonMap[0] = NKCODE_BUTTON_2; + SDLJoyButtonMap[1] = NKCODE_BUTTON_3; + SDLJoyButtonMap[2] = NKCODE_BUTTON_4; + SDLJoyButtonMap[3] = NKCODE_BUTTON_1; + SDLJoyButtonMap[4] = NKCODE_BUTTON_7; + SDLJoyButtonMap[5] = NKCODE_BUTTON_8; + SDLJoyButtonMap[6] = NKCODE_BUTTON_9; + SDLJoyButtonMap[7] = NKCODE_BUTTON_10; + SDLJoyButtonMap[8] = NKCODE_BUTTON_11; + SDLJoyButtonMap[9] = NKCODE_BUTTON_12; + SDLJoyButtonMap[10] = NKCODE_BUTTON_5; + SDLJoyButtonMap[11] = NKCODE_BUTTON_6; + SDLJoyButtonMap[12] = NKCODE_BUTTON_7; + SDLJoyButtonMap[13] = NKCODE_BUTTON_8; + SDLJoyButtonMap[14] = NKCODE_BUTTON_9; + + SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; + SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; + SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; + SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; + SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; + SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; +#else + SDLJoyButtonMap[0] = NKCODE_DPAD_UP; + SDLJoyButtonMap[1] = NKCODE_DPAD_DOWN; + SDLJoyButtonMap[2] = NKCODE_DPAD_LEFT; + SDLJoyButtonMap[3] = NKCODE_DPAD_RIGHT; + SDLJoyButtonMap[4] = NKCODE_BUTTON_10; + SDLJoyButtonMap[5] = NKCODE_BUTTON_9; + SDLJoyButtonMap[6] = NKCODE_BUTTON_5; + SDLJoyButtonMap[7] = NKCODE_BUTTON_6; + SDLJoyButtonMap[8] = NKCODE_BUTTON_7; + SDLJoyButtonMap[9] = NKCODE_BUTTON_8; + SDLJoyButtonMap[10] = NKCODE_BUTTON_SELECT; + SDLJoyButtonMap[11] = NKCODE_BUTTON_2; + SDLJoyButtonMap[12] = NKCODE_BUTTON_3; + SDLJoyButtonMap[13] = NKCODE_BUTTON_4; + SDLJoyButtonMap[14] = NKCODE_BUTTON_1; + + SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; + SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; + SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; + SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; + SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; + SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; +#endif + } + std::map SDLJoyButtonMap; + std::map SDLJoyAxisMap; + + SDL_Joystick *joy ; + SDL_Thread *thread ; + bool running ; + +}; diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index ff0b4b20a1..015222c1a5 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -80,7 +80,7 @@ void ControlMapper::Update(const InputState &input) { void ControlMapper::Refresh() { Clear(); - I18NCategory *c = GetI18NCategory("MappableControls"); + I18NCategory *mc = GetI18NCategory("MappableControls"); std::map keyImages; keyImages["Circle"] = I_CIRCLE; @@ -94,20 +94,26 @@ void ControlMapper::Refresh() { using namespace UI; + float itemH = 45; + LinearLayout *root = Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + root->SetSpacing(3.0f); + + const int padding = 4; auto iter = keyImages.find(keyName_); // First, look among images. if (iter != keyImages.end()) { - root->Add(new Choice(iter->second, new LinearLayoutParams(200, WRAP_CONTENT)))->OnClick.Handle(this, &ControlMapper::OnReplaceAll); + Choice *c = root->Add(new Choice(iter->second, new LinearLayoutParams(200, itemH))); + c->OnClick.Handle(this, &ControlMapper::OnReplaceAll); } else { // No image? Let's translate. - Choice *choice = new Choice(c->T(keyName_.c_str()), new LinearLayoutParams(200, WRAP_CONTENT)); - choice->SetCentered(true); - root->Add(choice)->OnClick.Handle(this, &ControlMapper::OnReplaceAll); + Choice *c = new Choice(mc->T(keyName_.c_str()), new LinearLayoutParams(200, itemH)); + c->SetCentered(true); + root->Add(c)->OnClick.Handle(this, &ControlMapper::OnReplaceAll); } - LinearLayout *rightColumn = root->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + LinearLayout *rightColumn = root->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); rightColumn->SetSpacing(2.0f); std::vector mappings; KeyMap::KeyFromPspButton(pspKey_, &mappings); @@ -118,23 +124,26 @@ void ControlMapper::Refresh() { int image = -1; LinearLayout *row = rightColumn->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + row->SetSpacing(1.0f); - Choice *c = row->Add(new Choice(deviceName + "." + keyName, new LinearLayoutParams(1.0f))); + Choice *c = row->Add(new Choice(deviceName + "." + keyName, new LinearLayoutParams(FILL_PARENT, itemH, 1.0f))); char tagbuf[16]; sprintf(tagbuf, "%i", (int)i); c->SetTag(tagbuf); c->OnClick.Handle(this, &ControlMapper::OnReplace); - Choice *d = row->Add(new Choice("X")); + Choice *d = row->Add(new Choice(" X ", new LayoutParams(FILL_PARENT, itemH))); d->SetTag(tagbuf); d->OnClick.Handle(this, &ControlMapper::OnDelete); - row->Add(new Choice("+"))->OnClick.Handle(this, &ControlMapper::OnAdd); + Choice *p = row->Add(new Choice(" + ", new LayoutParams(FILL_PARENT, itemH))); + p->OnClick.Handle(this, &ControlMapper::OnAdd); } if (mappings.size() == 0) { // look like an empty line - rightColumn->Add(new Choice("", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Handle(this, &ControlMapper::OnAdd); + Choice *c = rightColumn->Add(new Choice("", new LinearLayoutParams(FILL_PARENT, itemH))); + c->OnClick.Handle(this, &ControlMapper::OnAdd); } } @@ -194,11 +203,7 @@ void ControlMappingScreen::CreateViews() { leftColumn->Add(new Choice(k->T("Default All")))->OnClick.Handle(this, &ControlMappingScreen::OnDefaultMapping); leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f))); leftColumn->Add(new Choice(d->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); - /* - ChoiceStrip *mode = leftColumn->Add(new ChoiceStrip(ORIENT_VERTICAL)); - mode->AddChoice("Replace"); - mode->AddChoice("Add"); - */ + ScrollView *rightScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); rightScroll->SetScrollToTop(false); LinearLayout *rightColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); @@ -235,7 +240,6 @@ UI::EventReturn ControlMappingScreen::OnDefaultMapping(UI::EventParams ¶ms) return UI::EVENT_DONE; } - void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 4879f252ea..64f5c0030f 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -29,8 +29,11 @@ #include "Common/LogManager.h" #include "Core/MemMap.h" #include "Core/Config.h" +#include "Core/CoreParameter.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/JitCommon/JitCommon.h" +#include "GPU/GPUInterface.h" +#include "GPU/GPUState.h" #include "ext/disarm.h" #include "Common/CPUDetect.h" @@ -49,6 +52,8 @@ void DevMenu::CreatePopupContents(UI::ViewGroup *parent) { parent->Add(new Choice("Log Channels"))->OnClick.Handle(this, &DevMenu::OnLogConfig); parent->Add(new Choice("Developer Tools"))->OnClick.Handle(this, &DevMenu::OnDeveloperTools); parent->Add(new Choice("Jit Compare"))->OnClick.Handle(this, &DevMenu::OnJitCompare); + parent->Add(new Choice("Toggle Freeze"))->OnClick.Handle(this, &DevMenu::OnFreezeFrame); + parent->Add(new Choice("Dump Frame GPU Commands"))->OnClick.Handle(this, &DevMenu::OnDumpFrame); } UI::EventReturn DevMenu::OnLogConfig(UI::EventParams &e) { @@ -66,6 +71,20 @@ UI::EventReturn DevMenu::OnJitCompare(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn DevMenu::OnFreezeFrame(UI::EventParams &e) { + if (PSP_CoreParameter().frozen) { + PSP_CoreParameter().frozen = false; + } else { + PSP_CoreParameter().freezeNext = true; + } + return UI::EVENT_DONE; +} + +UI::EventReturn DevMenu::OnDumpFrame(UI::EventParams &e) { + gpu->DumpNextFrame(); + return UI::EVENT_DONE; +} + void DevMenu::dialogFinished(const Screen *dialog, DialogResult result) { // Close when a subscreen got closed. // TODO: a bug in screenmanager causes this not to work here. @@ -170,7 +189,7 @@ void SystemInfoScreen::CreateViews() { ViewGroup *leftColumn = new AnchorLayout(new LinearLayoutParams(1.0f)); root_->Add(leftColumn); - root_->Add(new Choice(d->T("Back"), "", false, new AnchorLayoutParams(225, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle(this, &UIScreen::OnBack); + root_->Add(new Choice(d->T("Back"), "", false, new AnchorLayoutParams(225, 64, 10, NONE, NONE, 10)))->OnClick.Handle(this, &UIScreen::OnBack); TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 225, new AnchorLayoutParams(10, 0, 10, 0, false)); @@ -201,6 +220,20 @@ void SystemInfoScreen::CreateViews() { openGL.resize(30); deviceSpecs->Add(new InfoItem("OpenGL", openGL)); deviceSpecs->Add(new InfoItem("GLSL", (char *)glGetString(GL_SHADING_LANGUAGE_VERSION))); + + ViewGroup *cpuExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + LinearLayout *cpuExtensions = new LinearLayout(ORIENT_VERTICAL); + cpuExtensions->SetSpacing(0); + cpuExtensionsScroll->Add(cpuExtensions); + + tabHolder->AddTab("CPU Extensions", cpuExtensionsScroll); + + cpuExtensions->Add(new ItemHeader("CPU Extensions")); + std::vector exts; + SplitString(cpu_info.Summarize(), ',', exts); + for (size_t i = 2; i < exts.size(); i++) { + cpuExtensions->Add(new TextView(exts[i])); + } ViewGroup *oglExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); LinearLayout *oglExtensions = new LinearLayout(ORIENT_VERTICAL); @@ -218,7 +251,7 @@ void SystemInfoScreen::CreateViews() { oglExtensions->Add(new ItemHeader("OpenGL ES 2.0 Extensions")); #endif - std::vector exts; + exts.clear(); SplitString(g_all_gl_extensions, ' ', exts); std::sort(exts.begin(), exts.end()); for (size_t i = 0; i < exts.size(); i++) { @@ -240,7 +273,91 @@ void SystemInfoScreen::CreateViews() { } } +void AddressPromptScreen::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + addrView_ = new TextView("Enter address", ALIGN_HCENTER, false); + parent->Add(addrView_); + + ViewGroup *grid = new GridLayout(GridLayoutSettings(60, 40)); + parent->Add(grid); + + for (int i = 0; i < 16; ++i) { + char temp[16]; + snprintf(temp, 16, " %X ", i); + buttons_[i] = new Button(temp); + grid->Add(buttons_[i])->OnClick.Handle(this, &AddressPromptScreen::OnDigitButton); + } + + parent->Add(new Button("Backspace"))->OnClick.Handle(this, &AddressPromptScreen::OnBackspace); +} + +void AddressPromptScreen::OnCompleted(DialogResult result) { + if (result == DR_OK) { + UI::EventParams e; + e.v = root_; + e.a = addr_; + OnChoice.Trigger(e); + } +} + +UI::EventReturn AddressPromptScreen::OnDigitButton(UI::EventParams &e) { + for (int i = 0; i < 16; ++i) { + if (buttons_[i] == e.v) { + AddDigit(i); + } + } + return UI::EVENT_DONE; +} + +UI::EventReturn AddressPromptScreen::OnBackspace(UI::EventParams &e) { + BackspaceDigit(); + return UI::EVENT_DONE; +} + +void AddressPromptScreen::AddDigit(int n) { + if ((addr_ & 0xF0000000) == 0) { + addr_ = addr_ * 16 + n; + } + UpdatePreviewDigits(); +} + +void AddressPromptScreen::BackspaceDigit() { + addr_ /= 16; + UpdatePreviewDigits(); +} + +void AddressPromptScreen::UpdatePreviewDigits() { + if (addr_ != 0) { + char temp[32]; + snprintf(temp, 32, "%8X", addr_); + addrView_->SetText(temp); + } else { + addrView_->SetText("Enter address"); + } +} + +void AddressPromptScreen::key(const KeyInput &key) { + int nextDigit = -1; + if (key.flags & KEY_DOWN) { + if (key.keyCode >= NKCODE_0 && key.keyCode <= NKCODE_9) { + AddDigit(key.keyCode - NKCODE_0); + } else if (key.keyCode >= NKCODE_A && key.keyCode <= NKCODE_F) { + AddDigit(10 + key.keyCode - NKCODE_A); + // NKCODE_DEL is backspace. + } else if (key.keyCode == NKCODE_DEL) { + BackspaceDigit(); + } else if (key.keyCode == NKCODE_ENTER) { + OnCompleted(DR_OK); + screenManager()->finishDialog(this, DR_OK); + return; + } else { + UIDialogScreen::key(key); + } + } else { + UIDialogScreen::key(key); + } +} // Three panes: Block chooser, MIPS view, ARM/x86 view void JitCompareScreen::CreateViews() { @@ -264,6 +381,7 @@ void JitCompareScreen::CreateViews() { rightDisasm_->SetSpacing(0.0f); leftColumn->Add(new Choice("Current"))->OnClick.Handle(this, &JitCompareScreen::OnCurrentBlock); + leftColumn->Add(new Choice("By Address"))->OnClick.Handle(this, &JitCompareScreen::OnSelectBlock); leftColumn->Add(new Choice("Random"))->OnClick.Handle(this, &JitCompareScreen::OnRandomBlock); leftColumn->Add(new Choice("Random VFPU"))->OnClick.Handle(this, &JitCompareScreen::OnRandomVFPUBlock); leftColumn->Add(new Choice(d->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); @@ -340,6 +458,24 @@ void JitCompareScreen::UpdateDisasm() { #endif } +UI::EventReturn JitCompareScreen::OnSelectBlock(UI::EventParams &e) { + auto addressPrompt = new AddressPromptScreen("Block address"); + addressPrompt->OnChoice.Handle(this, &JitCompareScreen::OnBlockAddress); + screenManager()->push(addressPrompt); + return UI::EVENT_DONE; +} + +UI::EventReturn JitCompareScreen::OnBlockAddress(UI::EventParams &e) { + JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache(); + if (Memory::IsValidAddress(e.a)) { + currentBlock_ = blockCache->GetBlockNumberFromStartAddress(e.a); + } else { + currentBlock_ = -1; + } + UpdateDisasm(); + return UI::EVENT_DONE; +} + UI::EventReturn JitCompareScreen::OnRandomBlock(UI::EventParams &e) { JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache(); int numBlocks = blockCache->GetNumBlocks(); diff --git a/UI/DevScreens.h b/UI/DevScreens.h index ed634236dd..9a9d9ee61d 100644 --- a/UI/DevScreens.h +++ b/UI/DevScreens.h @@ -38,6 +38,8 @@ public: protected: UI::EventReturn OnLogConfig(UI::EventParams &e); UI::EventReturn OnJitCompare(UI::EventParams &e); + UI::EventReturn OnFreezeFrame(UI::EventParams &e); + UI::EventReturn OnDumpFrame(UI::EventParams &e); UI::EventReturn OnDeveloperTools(UI::EventParams &e); }; @@ -67,6 +69,32 @@ public: virtual void CreateViews(); }; +class AddressPromptScreen : public PopupScreen { +public: + AddressPromptScreen(const std::string &title) : PopupScreen(title, "OK", "Cancel"), addrView_(NULL), addr_(0) { + memset(buttons_, 0, sizeof(buttons_)); + } + + virtual void key(const KeyInput &key); + + UI::Event OnChoice; + +protected: + void CreatePopupContents(UI::ViewGroup *parent); + virtual void OnCompleted(DialogResult result); + UI::EventReturn OnDigitButton(UI::EventParams &e); + UI::EventReturn OnBackspace(UI::EventParams &e); + +private: + void AddDigit(int n); + void BackspaceDigit(); + void UpdatePreviewDigits(); + + UI::TextView *addrView_; + UI::Button *buttons_[16]; + unsigned int addr_; +}; + class JitCompareScreen : public UIDialogScreenWithBackground { public: JitCompareScreen() : currentBlock_(-1) {} @@ -77,6 +105,8 @@ private: UI::EventReturn OnRandomBlock(UI::EventParams &e); UI::EventReturn OnRandomVFPUBlock(UI::EventParams &e); UI::EventReturn OnCurrentBlock(UI::EventParams &e); + UI::EventReturn OnSelectBlock(UI::EventParams &e); + UI::EventReturn OnBlockAddress(UI::EventParams &e); int currentBlock_; @@ -84,4 +114,4 @@ private: UI::LinearLayout *leftDisasm_; UI::LinearLayout *rightDisasm_; -}; \ No newline at end of file +}; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 021a7676d5..b05126ed6a 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -44,11 +44,10 @@ #include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/SaveState.h" -#include "UI/OnScreenDisplay.h" #include "UI/ui_atlas.h" +#include "UI/OnScreenDisplay.h" #include "UI/GamepadEmu.h" #include "UI/UIShader.h" - #include "UI/MainScreen.h" #include "UI/EmuScreen.h" #include "UI/DevScreens.h" @@ -56,7 +55,7 @@ #include "UI/MiscScreens.h" #include "UI/ControlMappingScreen.h" #include "UI/GameSettingsScreen.h" - +#include "UI/InstallZipScreen.h" EmuScreen::EmuScreen(const std::string &filename) : booted_(false), gamePath_(filename), invalid_(true), pauseTrigger_(false) { @@ -65,8 +64,6 @@ EmuScreen::EmuScreen(const std::string &filename) void EmuScreen::bootGame(const std::string &filename) { booted_ = true; std::string fileToStart = filename; - // This is probably where we should start up the emulated PSP. - INFO_LOG(BOOT, "Starting up hardware."); CoreParameter coreParam; coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; @@ -100,6 +97,7 @@ void EmuScreen::bootGame(const std::string &filename) { invalid_ = true; errorMessage_ = error_string; ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); + System_SendMessage("event", "failstartgame"); return; } @@ -126,6 +124,7 @@ void EmuScreen::bootGame(const std::string &filename) { osm.Show(s->T("Chainfire3DWarning", "WARNING: Chainfire3D detected, may cause problems"), 10.0f, 0xFF30a0FF, -1, true); } + System_SendMessage("event", "startgame"); } EmuScreen::~EmuScreen() { @@ -141,8 +140,8 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { // DR_YES means a message sent to PauseMenu by NativeMessageReceived. if (result == DR_OK) { screenManager()->switchScreen(new MainScreen()); + System_SendMessage("event", "exitgame"); } - RecreateViews(); } @@ -159,6 +158,7 @@ void EmuScreen::sendMessage(const char *message, const char *value) { if (!PSP_Init(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); screenManager()->switchScreen(new MainScreen()); + System_SendMessage("event", "failstartgame"); return; } host->BootDone(); @@ -170,29 +170,24 @@ void EmuScreen::sendMessage(const char *message, const char *value) { Core_EnableStepping(true); } #endif - } - else if (!strcmp(message, "boot")) { + } else if (!strcmp(message, "boot")) { PSP_Shutdown(); bootGame(value); - } - else if (!strcmp(message, "control mapping")) { + } else if (!strcmp(message, "control mapping")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new ControlMappingScreen()); - } - else if (!strcmp(message, "settings")) { + } else if (!strcmp(message, "settings")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new GameSettingsScreen(gamePath_)); - } - else if (!strcmp(message, "gpu resized")) { - if (gpu) gpu->Resized(); - } - else if (!strcmp(message, "gpu clear cache")) { - if (gpu) gpu->ClearCacheNextFrame(); - } - else if (!strcmp(message, "gpu dump next frame")) { + } else if (!strcmp(message, "gpu resized") || !strcmp(message, "gpu clear cache")) { + if (gpu) { + gpu->ClearCacheNextFrame(); + gpu->Resized(); + } + RecreateViews(); + } else if (!strcmp(message, "gpu dump next frame")) { if (gpu) gpu->DumpNextFrame(); - } - if (!strcmp(message, "clear jit")) { + } else if (!strcmp(message, "clear jit")) { if (MIPSComp::jit) { MIPSComp::jit->ClearCache(); } @@ -212,7 +207,6 @@ inline float tiltInputCurve(float x) { } else { return 0.0f; } - } inline float clamp1(float x) { @@ -266,6 +260,22 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) { case VIRTKEY_AXIS_RIGHT_Y_MAX: setVKeyAnalogY(CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX); break; + + case VIRTKEY_REWIND: + if (SaveState::CanRewind()) { + SaveState::Rewind(); + } else { + osm.Show(s->T("norewind", "No rewind save states available"), 2.0); + } + break; + case VIRTKEY_SAVE_STATE: + SaveState::SaveSlot(g_Config.iCurrentStateSlot, 0); + break; + case VIRTKEY_LOAD_STATE: + if (SaveState::HasSaveInSlot(g_Config.iCurrentStateSlot)) { + SaveState::LoadSlot(g_Config.iCurrentStateSlot, 0); + } + break; } } @@ -322,11 +332,11 @@ void EmuScreen::key(const KeyInput &key) { pauseTrigger_ = true; } - int result = KeyMap::KeyToPspButton(key.deviceId, key.keyCode); - if (result == KEYMAP_ERROR_UNKNOWN_KEY) - return; - - pspKey(result, key.flags); + std::vector pspKeys; + KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys); + for (size_t i = 0; i < pspKeys.size(); i++) { + pspKey(pspKeys[i], key.flags); + } } void EmuScreen::pspKey(int pspKeyCode, int flags) { @@ -362,51 +372,58 @@ void EmuScreen::axis(const AxisInput &axis) { } void EmuScreen::processAxis(const AxisInput &axis, int direction) { - int result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction); - int resultOpposite = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction); + std::vector results; + KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction, &results); + std::vector resultsOpposite; + KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite); - if (result == KEYMAP_ERROR_UNKNOWN_KEY) - return; + for (size_t i = 0; i < results.size(); i++) { + int result = results[i]; + switch (result) { + case VIRTKEY_AXIS_X_MIN: + __CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT); + break; + case VIRTKEY_AXIS_X_MAX: + __CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT); + break; + case VIRTKEY_AXIS_Y_MIN: + __CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT); + break; + case VIRTKEY_AXIS_Y_MAX: + __CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT); + break; - switch (result) { - case VIRTKEY_AXIS_X_MIN: - __CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_X_MAX: - __CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_Y_MIN: - __CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_Y_MAX: - __CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT); - break; + case VIRTKEY_AXIS_RIGHT_X_MIN: + __CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT); + break; + case VIRTKEY_AXIS_RIGHT_X_MAX: + __CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT); + break; + case VIRTKEY_AXIS_RIGHT_Y_MIN: + __CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT); + break; + case VIRTKEY_AXIS_RIGHT_Y_MAX: + __CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT); + break; - case VIRTKEY_AXIS_RIGHT_X_MIN: - __CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_X_MAX: - __CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_Y_MIN: - __CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_Y_MAX: - __CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT); - break; + default: + if (axis.value >= AXIS_BIND_THRESHOLD || axis.value <= -AXIS_BIND_THRESHOLD) { + pspKey(result, KEY_DOWN); - default: - if (axis.value >= AXIS_BIND_THRESHOLD || axis.value <= -AXIS_BIND_THRESHOLD) { - pspKey(result, KEY_DOWN); - - // Also unpress the other direction. - result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? -1 : 1); - if (result != KEYMAP_ERROR_UNKNOWN_KEY) + // Also unpress the other direction. + std::vector opposite; + KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? -1 : 1, &opposite); + for (size_t i = 0; i < opposite.size(); i++) { + pspKey(opposite[i], KEY_UP); + } + // Hm, why do we use a different way below? + } else { + // Release both directions, trying to deal with some erratic controllers that can cause it to stick. pspKey(result, KEY_UP); - } else { - // Release both directions, trying to deal with some erratic controllers that can cause it to stick. - pspKey(result, KEY_UP); - pspKey(resultOpposite, KEY_UP); + for (size_t i = 0; i < resultsOpposite.size(); i++) { + pspKey(resultsOpposite[i], KEY_UP); + } + } } } } @@ -454,15 +471,22 @@ void EmuScreen::update(InputState &input) { PSP_CoreParameter().pixelHeight = pixel_yres; UpdateUIState(UISTATE_INGAME); - + if (errorMessage_.size()) { + // Special handling for ZIP files. It's not very robust to check an error message but meh, + // at least it's pre-translation. + if (errorMessage_.find("ZIP") != std::string::npos) { + screenManager()->push(new InstallZipScreen(gamePath_)); + errorMessage_ = ""; + return; + } I18NCategory *g = GetI18NCategory("Error"); - std::string errLoadingFile = g->T("Error loading file"); + std::string errLoadingFile = g->T("Error loading file", "Could not load game"); + errLoadingFile.append(" "); errLoadingFile.append(g->T(errorMessage_.c_str())); - screenManager()->push(new PromptScreen( - errLoadingFile, "OK", "")); + screenManager()->push(new PromptScreen(errLoadingFile, "OK", "")); errorMessage_ = ""; return; } @@ -483,8 +507,7 @@ void EmuScreen::update(InputState &input) { #ifdef USING_GLES2 /* if (g_Config.bAccelerometerToAnalogHoriz) { - - //get the "base" coordinate system which is setup by the calibration system + // Get the "base" coordinate system which is setup by the calibration system float base_x = g_Config.fTiltBaseX; float base_y = g_Config.fTiltBaseY; @@ -514,7 +537,6 @@ void EmuScreen::update(InputState &input) { leftstick_y += clamp1(delta_y); __CtrlSetAnalogY(clamp1(leftstick_y), CTRL_STICK_LEFT); - } */ #endif @@ -535,6 +557,17 @@ void EmuScreen::render() { if (invalid_) return; + if (PSP_CoreParameter().freezeNext) { + PSP_CoreParameter().frozen = true; + PSP_CoreParameter().freezeNext = false; + SaveState::SaveToRam(freezeState_); + } else if (PSP_CoreParameter().frozen) { + if (CChunkFileReader::ERROR_NONE != SaveState::LoadFromRam(freezeState_)) { + ERROR_LOG(HLE, "Failed to load freeze state. Unfreezing."); + PSP_CoreParameter().frozen = false; + } + } + // Reapply the graphics state of the PSP ReapplyGfxState(); @@ -601,11 +634,13 @@ void EmuScreen::render() { char fpsbuf[256]; switch (g_Config.iShowFPSCounter) { case 1: - sprintf(fpsbuf, "Speed: %0.1f%%", vps / 60.0f * 100.0f); break; + sprintf(fpsbuf, "Speed: %0.1f%%", vps / (59.94f / 100.0f)); break; case 2: sprintf(fpsbuf, "FPS: %0.1f", actual_fps); break; case 3: - sprintf(fpsbuf, "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / 60.0f * 100.0f); break; + sprintf(fpsbuf, "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (59.94f / 100.0f)); break; + default: + return; } ui_draw2d.SetFontScale(0.7f, 0.7f); ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 8, 12, 0xc0000000, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII); @@ -631,6 +666,8 @@ void EmuScreen::deviceLost() { ILOG("EmuScreen::deviceLost()"); if (gpu) gpu->DeviceLost(); + + RecreateViews(); } void EmuScreen::autoLoad() { diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 890f692b3f..5fe07f38d8 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include "ui/screen.h" @@ -56,7 +57,7 @@ private: void setVKeyAnalogY(int stick, int virtualKeyMin, int virtualKeyMax); void autoLoad(); - + bool booted_; std::string gamePath_; @@ -69,4 +70,7 @@ private: // To track mappable virtual keys. We can have as many as we want. bool virtKeys[VIRTKEY_COUNT]; + + // In-memory save state used for freezeFrame, which is useful for debugging. + std::vector freezeState_; }; diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index c3afe08b80..79c471b91a 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -19,21 +19,22 @@ #include #include +#include "base/logging.h" #include "base/timeutil.h" #include "base/stringutil.h" #include "file/file_util.h" #include "file/zip_read.h" -#include "image/png_load.h" #include "thread/prioritizedworkqueue.h" +#include "Common/FileUtil.h" #include "Common/StringUtils.h" -#include "GameInfoCache.h" #include "Core/FileSystems/ISOFileSystem.h" #include "Core/FileSystems/DirectoryFileSystem.h" #include "Core/FileSystems/VirtualDiscFileSystem.h" #include "Core/ELF/PBPReader.h" #include "Core/System.h" - +#include "Core/Util/GameManager.h" #include "Core/Config.h" +#include "UI/GameInfoCache.h" GameInfoCache g_gameInfoCache; @@ -52,8 +53,24 @@ bool GameInfo::DeleteGame() { return true; } case FILETYPE_PSP_PBP_DIRECTORY: - // Recursively deleting directories not yet supported - return false; + { + // TODO: This could be handled by Core/Util/GameManager too somehow. + + const char *directoryToRemove = fileInfo.fullName.c_str(); + INFO_LOG(HLE, "Deleting %s", directoryToRemove); + if (!File::DeleteDirRecursively(directoryToRemove)) { + ERROR_LOG(HLE, "Failed to delete file"); + return false; + } + g_Config.CleanRecent(); + return true; + } + case FILETYPE_PSP_ELF: + { + const char *fileToRemove = fileInfo.fullName.c_str(); + deleteFile(fileToRemove); + return true; + } default: return false; @@ -75,7 +92,7 @@ std::vector GameInfo::GetSaveDataDirectories() { std::vector dirs; getFilesInDir(memc.c_str(), &dirs); - + std::vector directories; for (size_t i = 0; i < dirs.size(); i++) { if (startsWith(dirs[i].name, id)) { @@ -151,6 +168,44 @@ bool GameInfo::DeleteAllSaveData() { return true; } +void GameInfo::ParseParamSFO() { + title = paramSFO.GetValueString("TITLE"); + id = paramSFO.GetValueString("DISC_ID"); + id_version = paramSFO.GetValueString("DISC_ID") + "_" + paramSFO.GetValueString("DISC_VERSION"); + disc_total = paramSFO.GetValueInt("DISC_TOTAL"); + disc_number = paramSFO.GetValueInt("DISC_NUMBER"); + // region = paramSFO.GetValueInt("REGION"); // Always seems to be 32768? + + region = GAMEREGION_OTHER; + if (id_version.size() >= 4) { + std::string regStr = id_version.substr(0, 4); + + // Guesswork + switch (regStr[2]) { + case 'E': region = GAMEREGION_EUROPE; break; + case 'U': region = GAMEREGION_USA; break; + case 'J': region = GAMEREGION_JAPAN; break; + case 'H': region = GAMEREGION_HONGKONG; break; + case 'A': region = GAMEREGION_ASIA; break; + } + /* + if (regStr == "NPEZ" || regStr == "NPEG" || regStr == "ULES" || regStr == "UCES" || + regStr == "NPEX") { + region = GAMEREGION_EUROPE; + } else if (regStr == "NPUG" || regStr == "NPUZ" || regStr == "ULUS" || regStr == "UCUS") { + region = GAMEREGION_USA; + } else if (regStr == "NPJH" || regStr == "NPJG" || regStr == "ULJM"|| regStr == "ULJS") { + region = GAMEREGION_JAPAN; + } else if (regStr == "NPHG") { + region = GAMEREGION_HONGKONG; + } else if (regStr == "UCAS") { + region = GAMEREGION_CHINA; + }*/ + } + + paramSFOLoaded = true; +} + static bool ReadFileToString(IFileSystem *fs, const char *filename, std::string *contents, recursive_mutex *mtx) { PSPFileInfo info = fs->GetFileInfo(filename); if (!info.exists) { @@ -187,7 +242,10 @@ public: return; std::string filename = gamePath_; + info_->path = gamePath_; info_->fileType = Identify_File(filename); + // Fallback title + info_->title = getFilename(info_->path); switch (info_->fileType) { case FILETYPE_PSP_PBP: @@ -198,8 +256,13 @@ public: pbpFile += "/EBOOT.PBP"; PBPReader pbp(pbpFile.c_str()); - if (!pbp.IsValid()) + if (!pbp.IsValid()) { + if (pbp.IsELF()) { + goto handleELF; + } + ERROR_LOG(LOADER, "invalid pbp %s\n", pbpFile.c_str()); return; + } // First, PARAM.SFO. size_t sfoSize; @@ -207,11 +270,7 @@ public: { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO(sfoData, sfoSize); - info_->title = info_->paramSFO.GetValueString("TITLE"); - info_->id = info_->paramSFO.GetValueString("DISC_ID"); - info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); - - info_->paramSFOLoaded = true; + info_->ParseParamSFO(); } delete [] sfoData; @@ -223,7 +282,7 @@ public: } else { // Read standard icon size_t sz; - INFO_LOG(LOADER, "Loading unknown.png because a PBP was missing an icon"); + DEBUG_LOG(LOADER, "Loading unknown.png because a PBP was missing an icon"); uint8_t *contents = VFSReadFile("unknown.png", &sz); if (contents) { lock_guard lock(info_->lock); @@ -243,42 +302,37 @@ public: break; case FILETYPE_PSP_ELF: +handleELF: // An elf on its own has no usable information, no icons, no nothing. info_->title = getFilename(filename); info_->id = "ELF000000"; info_->id_version = "ELF000000_1.00"; info_->paramSFOLoaded = true; - { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("unknown.png", &sz); - INFO_LOG(LOADER, "Loading unknown.png because there was an ELF"); + DEBUG_LOG(LOADER, "Loading unknown.png because there was an ELF"); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); } delete [] contents; } - break; case FILETYPE_PSP_DISC_DIRECTORY: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; - VirtualDiscFileSystem umd(&handles,gamePath_.c_str()); - + VirtualDiscFileSystem umd(&handles, gamePath_.c_str()); + // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); - info_->title = info_->paramSFO.GetValueString("TITLE"); - info_->id = info_->paramSFO.GetValueString("DISC_ID"); - info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); - - info_->paramSFOLoaded = true; + info_->ParseParamSFO(); } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); @@ -306,35 +360,67 @@ public: if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); - info_->title = info_->paramSFO.GetValueString("TITLE"); - info_->id = info_->paramSFO.GetValueString("DISC_ID"); - info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); + info_->ParseParamSFO(); - info_->paramSFOLoaded = true; + ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); + if (info_->wantBG) { + ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); + } + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); } else { // Fall back to the filename for title if ISO is broken info_->title = gamePath_; + // Fall back to unknown icon if ISO is broken, override is allowed though + size_t sz; + uint8_t *contents = VFSReadFile("unknown.png", &sz); + DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found"); + if (contents) { + lock_guard lock(info_->lock); + info_->iconTextureData = std::string((const char *)contents, sz); + } + delete [] contents; } - - ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); - if (info_->wantBG) { - ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); - } - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); break; } - + + case FILETYPE_ARCHIVE_ZIP: + info_->title = getFilename(filename); + info_->paramSFOLoaded = true; + info_->wantBG = false; + { + // Read standard icon + size_t sz; + uint8_t *contents = VFSReadFile("zip.png", &sz); + if (contents) { + lock_guard lock(info_->lock); + info_->iconTextureData = std::string((const char *)contents, sz); + } + delete [] contents; + } + break; + + case FILETYPE_ARCHIVE_RAR: + info_->title = getFilename(filename); + info_->paramSFOLoaded = true; + info_->wantBG = false; + { + // Read standard icon + size_t sz; + uint8_t *contents = VFSReadFile("rargray.png", &sz); + if (contents) { + lock_guard lock(info_->lock); + info_->iconTextureData = std::string((const char *)contents, sz); + } + delete [] contents; + } + break; + case FILETYPE_NORMAL_DIRECTORY: - info_->title = gamePath_; - break; - default: - { - std::string fn, ext; - SplitPath(gamePath_, 0, &fn, &ext); - info_->title = fn + "." + ext; - } - break; + info_->title = getFilename(gamePath_); + info_->paramSFOLoaded = true; + info_->wantBG = false; + break; } // probably only want these when we ask for the background image... // should maybe flip the flag to "onlyIcon" @@ -402,6 +488,13 @@ void GameInfoCache::Clear() { delete iter->second->pic1Texture; iter->second->pic1Texture = 0; } + if (!iter->second->iconTextureData.empty()) { + iter->second->iconTextureData.clear(); + } + if (iter->second->iconTexture) { + delete iter->second->iconTexture; + iter->second->iconTexture = 0; + } } info_.clear(); } @@ -427,10 +520,6 @@ void GameInfoCache::FlushBGs() { } } -void GameInfoCache::Add(const std::string &key, GameInfo *info_) { - -} - // This may run off-main-thread and we thus can't use the global // pspFileSystem (well, we could with synchronization but there might not // even be a game running). @@ -446,9 +535,8 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { { lock_guard lock(info->lock); if (info->iconTextureData.size()) { - info->iconTexture = new Texture(); - // TODO: We could actually do the PNG decoding as well on the async thread. // We'd have to split up Texture->LoadPNG though, creating some intermediate Image class maybe. + info->iconTexture = new Texture(); if (info->iconTexture->LoadPNG((const u8 *)info->iconTextureData.data(), info->iconTextureData.size(), false)) { info->timeIconWasLoaded = time_now_d(); } else { diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 0d4be8c5b3..696f6e4826 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -27,15 +27,26 @@ #include "Core/ELF/ParamSFO.h" #include "Core/Loaders.h" - // A GameInfo holds information about a game, and also lets you do things that the VSH // does on the PSP, namely checking for and deleting savedata, and similar things. +// Only cares about games that are installed on the current device. + +// Guessed from GameID, not necessarily accurate +enum GameRegion { + GAMEREGION_JAPAN, + GAMEREGION_USA, + GAMEREGION_EUROPE, + GAMEREGION_HONGKONG, + GAMEREGION_ASIA, + GAMEREGION_OTHER, + GAMEREGION_MAX, +}; class GameInfo { public: - GameInfo() + GameInfo() : fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false), iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), - wantBG(false), gameSize(0), saveDataSize(0), installDataSize(0) {} + wantBG(false), gameSize(0), saveDataSize(0), installDataSize(0), disc_total(0), disc_number(0), region(-1) {} bool DeleteGame(); // Better be sure what you're doing when calling this. bool DeleteAllSaveData(); @@ -44,7 +55,7 @@ public: u64 GetSaveDataSizeInBytes(); u64 GetInstallDataSizeInBytes(); - void LoadParamSFO(); + void ParseParamSFO(); std::vector GetSaveDataDirectories(); @@ -56,13 +67,17 @@ public: recursive_mutex lock; FileInfo fileInfo; + std::string path; std::string title; // for easy access, also available in paramSFO. std::string id; std::string id_version; + int disc_total; + int disc_number; + int region; IdentifiedFileType fileType; ParamSFOData paramSFO; bool paramSFOLoaded; - + // Pre read the data, create a texture the next time (GL thread..) std::string iconTextureData; Texture *iconTexture; @@ -108,8 +123,6 @@ public: void Save(); void Load(); - void Add(const std::string &key, GameInfo *info_); - private: // Maps ISO path to info. std::map info_; diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index ff88db4917..8dde8d4315 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -20,6 +20,7 @@ #include "gfx_es2/draw_buffer.h" #include "i18n/i18n.h" #include "math/curves.h" +#include "util/text/utf8.h" #include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -57,6 +58,7 @@ void GameScreen::CreateViews() { tvGameSize_ = leftColumn->Add(new TextView("...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 250, NONE, NONE))); tvSaveDataSize_ = leftColumn->Add(new TextView("...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 290, NONE, NONE))); tvInstallDataSize_ = leftColumn->Add(new TextView("", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 330, NONE, NONE))); + tvRegion_ = leftColumn->Add(new TextView("", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 370, NONE, NONE))); } ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); @@ -76,6 +78,9 @@ void GameScreen::CreateViews() { if (isRecentGame(gamePath_)) { rightColumnItems->Add(new Choice(ga->T("Remove From Recent")))->OnClick.Handle(this, &GameScreen::OnRemoveFromRecent); } +#ifdef _WIN32 + rightColumnItems->Add(new Choice(ga->T("Show In Folder")))->OnClick.Handle(this, &GameScreen::OnShowInFolder); +#endif UI::SetFocusedView(play); } @@ -135,6 +140,25 @@ void GameScreen::update(InputState &input) { tvInstallDataSize_->SetText(temp); } } + + if (info->region >= 0 && info->region < GAMEREGION_MAX && info->region != GAMEREGION_OTHER) { + static const char *regionNames[GAMEREGION_MAX] = { + "Japan", + "USA", + "Europe", + "Hong Kong", + "Asia" + }; + tvRegion_->SetText(ga->T(regionNames[info->region])); + } +} + +UI::EventReturn GameScreen::OnShowInFolder(UI::EventParams &e) { +#ifdef _WIN32 + std::string str = std::string("explorer.exe /select,\"") + ReplaceAll(gamePath_, "/", "\\") + "\""; + _wsystem(ConvertUTF8ToWString(str).c_str()); +#endif + return UI::EVENT_DONE; } UI::EventReturn GameScreen::OnSwitchBack(UI::EventParams &e) { @@ -211,7 +235,11 @@ UI::EventReturn GameScreen::OnCreateShortcut(UI::EventParams &e) { bool GameScreen::isRecentGame(std::string gamePath) { for (auto it = g_Config.recentIsos.begin(); it != g_Config.recentIsos.end(); ++it) { - if (!strcmp((*it).c_str(),gamePath.c_str())) +#ifdef _WIN32 + if (!strcmpIgnore((*it).c_str(), gamePath.c_str(), "\\","/")) +#else + if (!strcmp((*it).c_str(), gamePath.c_str())) +#endif return true; } return false; @@ -219,7 +247,11 @@ bool GameScreen::isRecentGame(std::string gamePath) { UI::EventReturn GameScreen::OnRemoveFromRecent(UI::EventParams &e) { for (auto it = g_Config.recentIsos.begin(); it != g_Config.recentIsos.end(); ++it) { - if (!strcmp((*it).c_str(),gamePath_.c_str())) { +#ifdef _WIN32 + if (!strcmpIgnore((*it).c_str(), gamePath_.c_str(), "\\","/")) { +#else + if (!strcmp((*it).c_str(), gamePath_.c_str())) { +#endif g_Config.recentIsos.erase(it); screenManager()->switchScreen(new MainScreen()); return UI::EVENT_DONE; diff --git a/UI/GameScreen.h b/UI/GameScreen.h index dbecc2712c..2498088ea5 100644 --- a/UI/GameScreen.h +++ b/UI/GameScreen.h @@ -48,6 +48,7 @@ private: UI::EventReturn OnSwitchBack(UI::EventParams &e); UI::EventReturn OnCreateShortcut(UI::EventParams &e); UI::EventReturn OnRemoveFromRecent(UI::EventParams &e); + UI::EventReturn OnShowInFolder(UI::EventParams &e); std::string gamePath_; @@ -57,4 +58,5 @@ private: UI::TextView *tvGameSize_; UI::TextView *tvSaveDataSize_; UI::TextView *tvInstallDataSize_; + UI::TextView *tvRegion_; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 94c083efe0..626c921359 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -26,6 +26,7 @@ #include "UI/EmuScreen.h" #include "UI/GameSettingsScreen.h" #include "UI/GameInfoCache.h" +#include "UI/GamepadEmu.h" #include "UI/MiscScreens.h" #include "UI/ControlMappingScreen.h" #include "UI/DevScreens.h" @@ -47,8 +48,9 @@ namespace MainWindow { extern HWND hwndMain; } #endif + #ifdef IOS -extern bool isJailed; +extern bool iosCanUseJit; #endif static const int alternateSpeedTable[9] = { @@ -87,7 +89,7 @@ void GameSettingsScreen::CreateViews() { ViewGroup *leftColumn = new AnchorLayout(new LinearLayoutParams(1.0f)); root_->Add(leftColumn); - root_->Add(new Choice(d->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle(this, &UIScreen::OnBack); + root_->Add(new Choice(d->T("Back"), "", false, new AnchorLayoutParams(150, 64, 10, NONE, NONE, 10)))->OnClick.Handle(this, &UIScreen::OnBack); TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false)); @@ -119,14 +121,12 @@ void GameSettingsScreen::CreateViews() { postProcChoice_->OnClick.Handle(this, &GameSettingsScreen::OnPostProcShader); postProcChoice_->SetEnabled(g_Config.iRenderingMode != 0); -#ifdef _WIN32 +#if defined(_WIN32) || defined(USING_QT_UI) graphicsSettings->Add(new CheckBox(&g_Config.bFullScreen, gs->T("FullScreen")))->OnClick.Handle(this, &GameSettingsScreen::OnFullscreenChange); #endif graphicsSettings->Add(new CheckBox(&g_Config.bStretchToDisplay, gs->T("Stretch to Display"))); -#ifdef BLACKBERRY - if (pixel_xres == pixel_yres) + if (pixel_xres < pixel_yres * 1.3) // Smaller than 4:3 graphicsSettings->Add(new CheckBox(&g_Config.bPartialStretch, gs->T("Partial Vertical Stretch"))); -#endif graphicsSettings->Add(new CheckBox(&g_Config.bMipMap, gs->T("Mipmapping"))); graphicsSettings->Add(new ItemHeader(gs->T("Performance"))); @@ -143,16 +143,19 @@ void GameSettingsScreen::CreateViews() { graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gs->T("VSync"))); #endif graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTransform, gs->T("Hardware Transform"))); + CheckBox *swSkin = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareSkinning, gs->T("Software Skinning"))); graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gs->T("Vertex Cache"))); - CheckBox *vtxJit = graphicsSettings->Add(new CheckBox(&g_Config.bVertexDecoderJit, gs->T("Vertex Decoder JIT"))); - if (PSP_IsInited()) - vtxJit->SetEnabled(false); + + // Seems solid, so we hide the setting. + // CheckBox *vtxJit = graphicsSettings->Add(new CheckBox(&g_Config.bVertexDecoderJit, gs->T("Vertex Decoder JIT"))); + + if (PSP_IsInited()) { + swSkin->SetEnabled(false); + // vtxJit->SetEnabled(false); + } graphicsSettings->Add(new CheckBox(&g_Config.bLowQualitySplineBezier, gs->T("LowCurves", "Low quality spline/bezier curves"))); - // This setting is not really useful for anyone atm. - // graphicsSettings->Add(new CheckBox(&g_Config.bTrueColor, gs->T("True Color"))); - // In case we're going to add few other antialiasing option like MSAA in the future. // graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gs->T("FXAA"))); graphicsSettings->Add(new ItemHeader(gs->T("Texture Scaling"))); @@ -172,6 +175,7 @@ void GameSettingsScreen::CreateViews() { graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexFiltering, gs->T("Texture Filter"), texFilters, 1, ARRAY_SIZE(texFilters), gs, screenManager())); graphicsSettings->Add(new ItemHeader(gs->T("Hack Settings", "Hack Settings (these WILL cause glitches)"))); + graphicsSettings->Add(new CheckBox(&g_Config.bTimerHack, gs->T("Timer Hack"))); // Maybe hide this on non-PVR? graphicsSettings->Add(new CheckBox(&g_Config.bDisableAlphaTest, gs->T("Disable Alpha Test (PowerVR speedup)")))->OnClick.Handle(this, &GameSettingsScreen::OnShaderChange); graphicsSettings->Add(new CheckBox(&g_Config.bDisableStencilTest, gs->T("Disable Stencil Test"))); @@ -181,11 +185,12 @@ void GameSettingsScreen::CreateViews() { prescale->SetEnabled(false); graphicsSettings->Add(new ItemHeader(gs->T("Overlay Information"))); - static const char *fpsChoices[] = {"None", "Speed", "FPS", "Both" + static const char *fpsChoices[] = { + "None", "Speed", "FPS", "Both" #ifdef BLACKBERRY - , "Statistics" + , "Statistics" #endif - }; + }; graphicsSettings->Add(new PopupMultiChoice(&g_Config.iShowFPSCounter, gs->T("Show FPS Counter"), fpsChoices, 0, ARRAY_SIZE(fpsChoices), gs, screenManager())); graphicsSettings->Add(new CheckBox(&showDebugStats_, gs->T("Show Debug Statistics"))); @@ -196,12 +201,10 @@ void GameSettingsScreen::CreateViews() { if (!PSP_IsInited()) dump->SetEnabled(false); -#ifndef __SYMBIAN32__ // We normally use software rendering to debug so put it in debugging. CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gs->T("Software Rendering", "Software Rendering (experimental)"))); if (PSP_IsInited()) softwareGPU->SetEnabled(false); -#endif // Audio ViewGroup *audioSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); @@ -241,8 +244,13 @@ void GameSettingsScreen::CreateViews() { layoutEditorChoice_ = controlsSettings->Add(new Choice(c->T("Custom layout..."))); layoutEditorChoice_->OnClick.Handle(this, &GameSettingsScreen::OnTouchControlLayout); layoutEditorChoice_->SetEnabledPtr(&g_Config.bShowTouchControls); - controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, c->T("Button Opacity"), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fButtonScale, 0.80, 2.0, c->T("Button Scaling"), screenManager())); + CheckBox *disableDiags = controlsSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, c->T("Disable D-Pad diagonals (4-way touch)"))); + disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls); + View *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, c->T("Button Opacity"), screenManager())); + opacity->SetEnabledPtr(&g_Config.bShowTouchControls); + static const char *touchControlStyles[] = {"Classic", "Thin borders"}; + View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, c->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), c, screenManager())); + style->SetEnabledPtr(&g_Config.bShowTouchControls); // System ViewGroup *systemSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); @@ -257,16 +265,32 @@ void GameSettingsScreen::CreateViews() { systemSettings->Add(new ItemHeader(s->T("Emulation"))); systemSettings->Add(new CheckBox(&g_Config.bFastMemory, s->T("Fast Memory", "Fast Memory (Unstable)"))); -#ifndef __SYMBIAN32__ systemSettings->Add(new CheckBox(&g_Config.bSeparateCPUThread, s->T("Multithreaded (experimental)")))->SetEnabled(!PSP_IsInited()); systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, s->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited()); -#endif - systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, s->T("Change CPU Clock", "Change CPU Clock (0 = default)"), screenManager())); + systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, s->T("Change CPU Clock", "Change CPU Clock (0 = default) (unstable)"), screenManager())); +#ifndef USING_GLES2 systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, s->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (0 = off, mem hog)"), screenManager())); +#endif systemSettings->Add(new CheckBox(&g_Config.bAtomicAudioLocks, s->T("Atomic Audio locks (experimental)")))->SetEnabled(!PSP_IsInited()); + systemSettings->Add(new ItemHeader(s->T("Developer Tools"))); + systemSettings->Add(new Choice(s->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools); + + systemSettings->Add(new ItemHeader(s->T("General"))); + systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, s->T("VersionCheck", "Check for new versions of PPSSPP"))); + systemSettings->Add(new Choice(s->T("Clear Recent Games List")))->OnClick.Handle(this, &GameSettingsScreen::OnClearRecents); + systemSettings->Add(new Choice(s->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); + systemSettings->Add(new CheckBox(&g_Config.bEnableAutoLoad, s->T("Auto Load Newest Savestate"))); + enableReports_ = Reporting::IsEnabled(); + enableReportsCheckbox_ = new CheckBox(&enableReports_, s->T("Enable Compatibility Server Reports")); + enableReportsCheckbox_->SetEnabled(Reporting::IsSupported()); + systemSettings->Add(enableReportsCheckbox_); + + systemSettings->Add(new ItemHeader(s->T("Networking"))); + systemSettings->Add(new CheckBox(&g_Config.bEnableWlan, s->T("Enable networking", "Enable networking/wlan (beta)"))); + //#ifndef ANDROID systemSettings->Add(new ItemHeader(s->T("Cheats", "Cheats (experimental, see forums)"))); systemSettings->Add(new CheckBox(&g_Config.bEnableCheats, s->T("Enable Cheats"))); @@ -274,24 +298,16 @@ void GameSettingsScreen::CreateViews() { LinearLayout *list = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); systemSettings->SetSpacing(0); - systemSettings->Add(new ItemHeader(s->T("General"))); - systemSettings->Add(new Choice(s->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools); - systemSettings->Add(new Choice(s->T("Clear Recent Games List")))->OnClick.Handle(this, &GameSettingsScreen::OnClearRecents); - systemSettings->Add(new Choice(s->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); - systemSettings->Add(new CheckBox(&g_Config.bEnableAutoLoad, s->T("Auto Load Newest Savestate"))); - enableReportsCheckbox_ = new CheckBox(&enableReports_, s->T("Enable Compatibility Server Reports")); - enableReportsCheckbox_->SetEnabled(Reporting::IsSupported()); - systemSettings->Add(enableReportsCheckbox_); - - systemSettings->Add(new ItemHeader(s->T("PSP Settings"))); // TODO: Come up with a way to display a keyboard for mobile users, // so until then, this is Windows/Desktop only. -#ifdef _WIN32 +#if defined(_WIN32) || defined(USING_QT_UI) systemSettings->Add(new Choice(s->T("Change Nickname")))->OnClick.Handle(this, &GameSettingsScreen::OnChangeNickname); - // Screenshot functionality is not yet available on non-Windows +#endif +#if defined(_WIN32) || (defined(USING_QT_UI) && !defined(USING_GLES2)) + // Screenshot functionality is not yet available on non-Windows/non-Qt systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, s->T("Screenshots as PNG"))); -#endif +#endif systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, s->T("Day Light Saving"))); static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY"}; systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, s->T("Date Format"), dateFormat, 1, 3, s, screenManager())); @@ -426,18 +442,17 @@ void GlobalSettingsScreen::CreateViews() { }*/ UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) { - #ifdef _WIN32 - +#if defined(_WIN32) || defined(USING_QT_UI) const size_t name_len = 256; char name[name_len]; memset(name, 0, sizeof(name)); - if (host->InputBoxGetString("Enter a new PSP nickname", g_Config.sNickName.c_str(), name, name_len)) { + if (System_InputBoxGetString("Enter a new PSP nickname", g_Config.sNickName.c_str(), name, name_len)) { g_Config.sNickName = name; } +#endif - #endif return UI::EVENT_DONE; } @@ -507,7 +522,7 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new ItemHeader(s->T("General"))); #ifdef IOS - if (isJailed) { + if (!iosCanUseJit) { list->Add(new TextView(s->T("DynarecisJailed", "Dynarec (JIT) - (Not jailbroken - JIT not available)"))); } else { list->Add(new CheckBox(&g_Config.bJit, s->T("Dynarec", "Dynarec (JIT)"))); diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index ae989e71bf..cb138171c7 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -77,19 +77,6 @@ private: bool showDebugStats_; }; -/* -class GlobalSettingsScreen : public UIDialogScreenWithBackground { -public: - GlobalSettingsScreen() {} - -protected: - virtual void CreateViews(); - -private: - // Temporaries to convert bools to other kinds of settings -};*/ - - class DeveloperToolsScreen : public UIDialogScreenWithBackground { public: DeveloperToolsScreen() {} diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index ebef4af128..7058fab436 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -34,6 +34,10 @@ #define USE_PAUSE_BUTTON 0 #endif +static u32 GetButtonColor() { + return g_Config.iTouchButtonStyle == 1 ? 0xFFFFFF : 0xc0b080; +} + void MultiTouchButton::GetContentDimensions(const UIContext &dc, float &w, float &h) const { const AtlasImage &image = dc.Draw()->GetAtlas()->images[bgImg_]; w = image.w * scale_; @@ -63,11 +67,17 @@ void MultiTouchButton::Draw(UIContext &dc) { scale *= 2.0f; opacity *= 1.15f; } - uint32_t colorBg = colorAlpha(0xc0b080, opacity); + uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); uint32_t color = colorAlpha(0xFFFFFF, opacity); dc.Draw()->DrawImageRotated(bgImg_, bounds_.centerX(), bounds_.centerY(), scale, angle_ * (M_PI * 2 / 360.0f), colorBg, flipImageH_); - dc.Draw()->DrawImageRotated(img_, bounds_.centerX(), bounds_.centerY(), scale, angle_ * (M_PI * 2 / 360.0f), color); + + int y = bounds_.centerY(); + // Hack round the fact that the center of the rectangular picture the triangle is contained in + // is not at the "weight center" of the triangle. + if (img_ == I_TRIANGLE) + y -= 2.8f * scale; + dc.Draw()->DrawImageRotated(img_, bounds_.centerX(), y, scale, angle_ * (M_PI * 2 / 360.0f), color); } void BoolButton::Touch(const TouchInput &input) { @@ -98,17 +108,17 @@ bool PSPButton::IsDown() { return (__CtrlPeekButtons() & pspButtonBit_) != 0; } - -PSPCross::PSPCross(int arrowIndex, int overlayIndex, float scale, float radius, UI::LayoutParams *layoutParams) - : UI::View(layoutParams), arrowIndex_(arrowIndex), overlayIndex_(overlayIndex), scale_(scale), radius_(radius), dragPointerId_(-1), down_(0) { +PSPDpad::PSPDpad(int arrowIndex, int overlayIndex, float scale, float spacing, UI::LayoutParams *layoutParams) + : UI::View(layoutParams), arrowIndex_(arrowIndex), overlayIndex_(overlayIndex), + scale_(scale), spacing_(spacing), dragPointerId_(-1), down_(0) { } -void PSPCross::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - w = radius_ * 4; - h = radius_ * 4; +void PSPDpad::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = D_pad_Radius * spacing_ * 4; + h = D_pad_Radius * spacing_ * 4; } -void PSPCross::Touch(const TouchInput &input) { +void PSPDpad::Touch(const TouchInput &input) { int lastDown = down_; if (input.flags & TOUCH_DOWN) { @@ -130,30 +140,44 @@ void PSPCross::Touch(const TouchInput &input) { } } -void PSPCross::ProcessTouch(float x, float y, bool down) { - float stick_size_ = radius_; - float inv_stick_size = 1.0f / (stick_size_ * scale_); +void PSPDpad::ProcessTouch(float x, float y, bool down) { + float stick_size = spacing_ * D_pad_Radius * scale_; + float inv_stick_size = 1.0f / (stick_size * scale_); const float deadzone = 0.17f; float dx = (x - bounds_.centerX()) * inv_stick_size; float dy = (y - bounds_.centerY()) * inv_stick_size; - float rad = sqrtf(dx*dx+dy*dy); + float rad = sqrtf(dx*dx + dy*dy); if (rad < deadzone || rad > 2.0f) down = false; int ctrlMask = 0; int lastDown = down_; + + bool fourWay = g_Config.bDisableDpadDiagonals || rad < 0.7f; if (down) { - int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; - switch (direction) { - case 0: ctrlMask |= CTRL_RIGHT; break; - case 1: ctrlMask |= CTRL_RIGHT | CTRL_DOWN; break; - case 2: ctrlMask |= CTRL_DOWN; break; - case 3: ctrlMask |= CTRL_DOWN | CTRL_LEFT; break; - case 4: ctrlMask |= CTRL_LEFT; break; - case 5: ctrlMask |= CTRL_UP | CTRL_LEFT; break; - case 6: ctrlMask |= CTRL_UP; break; - case 7: ctrlMask |= CTRL_UP | CTRL_RIGHT; break; + if (fourWay) { + int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 4) + 0.5f)) & 3; + switch (direction) { + case 0: ctrlMask |= CTRL_RIGHT; break; + case 1: ctrlMask |= CTRL_DOWN; break; + case 2: ctrlMask |= CTRL_LEFT; break; + case 3: ctrlMask |= CTRL_UP; break; + } + // 4 way pad + } else { + // 8 way pad + int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; + switch (direction) { + case 0: ctrlMask |= CTRL_RIGHT; break; + case 1: ctrlMask |= CTRL_RIGHT | CTRL_DOWN; break; + case 2: ctrlMask |= CTRL_DOWN; break; + case 3: ctrlMask |= CTRL_DOWN | CTRL_LEFT; break; + case 4: ctrlMask |= CTRL_LEFT; break; + case 5: ctrlMask |= CTRL_UP | CTRL_LEFT; break; + case 6: ctrlMask |= CTRL_UP; break; + case 7: ctrlMask |= CTRL_UP | CTRL_RIGHT; break; + } } } @@ -174,28 +198,31 @@ void PSPCross::ProcessTouch(float x, float y, bool down) { } } -void PSPCross::Draw(UIContext &dc) { +void PSPDpad::Draw(UIContext &dc) { float opacity = g_Config.iTouchButtonOpacity / 100.0f; - uint32_t colorBg = colorAlpha(0xc0b080, opacity); + uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); uint32_t color = colorAlpha(0xFFFFFF, opacity); static const float xoff[4] = {1, 0, -1, 0}; static const float yoff[4] = {0, 1, 0, -1}; static const int dir[4] = {CTRL_RIGHT, CTRL_DOWN, CTRL_LEFT, CTRL_UP}; int buttons = __CtrlPeekButtons(); + float r = D_pad_Radius * spacing_; for (int i = 0; i < 4; i++) { - float x = bounds_.centerX() + xoff[i] * radius_; - float y = bounds_.centerY() + yoff[i] * radius_; + float x = bounds_.centerX() + xoff[i] * r; + float y = bounds_.centerY() + yoff[i] * r; + float x2 = bounds_.centerX() + xoff[i] * (r + 10.f * scale_); + float y2 = bounds_.centerY() + yoff[i] * (r + 10.f * scale_); float angle = i * M_PI / 2; float imgScale = (buttons & dir[i]) ? scale_ * 2 : scale_; dc.Draw()->DrawImageRotated(arrowIndex_, x, y, imgScale, angle + PI, colorBg, false); if (overlayIndex_ != -1) - dc.Draw()->DrawImageRotated(overlayIndex_, x, y, imgScale, angle + PI, color); + dc.Draw()->DrawImageRotated(overlayIndex_, x2, y2, imgScale, angle + PI, color); } } -PSPStick::PSPStick(int bgImg, int stickImg, int stick, float scale, UI::LayoutParams *layoutParams) +PSPStick::PSPStick(int bgImg, int stickImg, int stick, float scale, UI::LayoutParams *layoutParams) : UI::View(layoutParams), dragPointerId_(-1), bgImg_(bgImg), stickImageIndex_(stickImg), stick_(stick), scale_(scale) { stick_size_ = 50; } @@ -209,7 +236,7 @@ void PSPStick::GetContentDimensions(const UIContext &dc, float &w, float &h) con void PSPStick::Draw(UIContext &dc) { float opacity = g_Config.iTouchButtonOpacity / 100.0f; - uint32_t colorBg = colorAlpha(0xc0b080, opacity); + uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); uint32_t color = colorAlpha(0x808080, opacity); float stickX = bounds_.centerX(); @@ -269,45 +296,37 @@ void PSPStick::ProcessTouch(float x, float y, bool down) { } } -void InitPadLayout() { +void InitPadLayout(float globalScale) { + const float scale = globalScale; - // TODO: See if we can make some kind of global scaling for views instead of this hackery. - float scale = g_Config.fButtonScale; - - //PSP buttons (triangle, circle, square, cross)--------------------- - //space between the PSP buttons (triangle, circle, square and cross) - const int Action_button_spacing = 50 * scale; - - if (g_Config.iActionButtonSpacing == -1) { - g_Config.iActionButtonSpacing = Action_button_spacing; + // PSP buttons (triangle, circle, square, cross)--------------------- + // space between the PSP buttons (triangle, circle, square and cross) + if (g_Config.fActionButtonSpacing < 0) { + g_Config.fActionButtonSpacing = 1.0f; } - //position of the circle button (the PSP circle button). It is the farthest to the left + // Position of the circle button (the PSP circle button). It is the farthest to the left + float Action_button_spacing = g_Config.fActionButtonSpacing * baseActionButtonSpacing; int Action_button_center_X = dp_xres - Action_button_spacing * 2; int Action_button_center_Y = dp_yres - Action_button_spacing * 2; - if(g_Config.fActionButtonCenterX == -1.0 || g_Config.fActionButtonCenterY == -1.0 ) { - //setup defaults + if (g_Config.fActionButtonCenterX == -1.0 || g_Config.fActionButtonCenterY == -1.0) { + // Setup defaults g_Config.fActionButtonCenterX = (float)Action_button_center_X / dp_xres; g_Config.fActionButtonCenterY = (float)Action_button_center_Y / dp_yres; } - - //D-PAD (up down left right) (aka PSP cross)-------------------------------------------------------------- + //D-PAD (up down left right) (aka PSP cross)---------------------------- //radius to the D-pad - const int D_pad_Radius = 40 * scale; + // TODO: Make configurable - if (g_Config.iDpadRadius == -1) { - g_Config.iDpadRadius = D_pad_Radius; - } - - int D_pad_X = 2.5 * D_pad_Radius; - int D_pad_Y = dp_yres - D_pad_Radius; + int D_pad_X = 2.5 * D_pad_Radius * scale; + int D_pad_Y = dp_yres - D_pad_Radius * scale; if (g_Config.bShowTouchAnalogStick) { D_pad_Y -= 200 * scale; } - if(g_Config.fDpadX == -1.0 || g_Config.fDpadY == -1.0 ) { + if (g_Config.fDpadX == -1.0 || g_Config.fDpadY == -1.0 ) { //setup defaults g_Config.fDpadX = (float)D_pad_X / dp_xres; g_Config.fDpadY = (float)D_pad_Y / dp_yres; @@ -321,18 +340,20 @@ void InitPadLayout() { if (g_Config.fAnalogStickX == -1.0 || g_Config.fAnalogStickY == -1.0 ) { g_Config.fAnalogStickX = (float)analog_stick_X / dp_xres; g_Config.fAnalogStickY = (float)analog_stick_Y / dp_yres; + g_Config.fAnalogStickScale = scale; } //select, start, throttle-------------------------------------------- //space between the bottom keys (space between select, start and un-throttle) const int bottom_key_spacing = 100 * scale; - + int start_key_X = dp_xres / 2 + (bottom_key_spacing) * scale; int start_key_Y = dp_yres - 60 * scale; if (g_Config.fStartKeyX == -1.0 || g_Config.fStartKeyY == -1.0 ) { g_Config.fStartKeyX = (float)start_key_X / dp_xres; g_Config.fStartKeyY = (float)start_key_Y / dp_yres; + g_Config.fStartKeyScale = scale; } int select_key_X = dp_xres / 2; @@ -341,6 +362,7 @@ void InitPadLayout() { if (g_Config.fSelectKeyX == -1.0 || g_Config.fSelectKeyY == -1.0 ) { g_Config.fSelectKeyX = (float)select_key_X / dp_xres; g_Config.fSelectKeyY = (float)select_key_Y / dp_yres; + g_Config.fSelectKeyScale = scale; } int unthrottle_key_X = dp_xres / 2 - (bottom_key_spacing) * scale; @@ -349,6 +371,7 @@ void InitPadLayout() { if (g_Config.fUnthrottleKeyX == -1.0 || g_Config.fUnthrottleKeyY == -1.0 ) { g_Config.fUnthrottleKeyX = (float)unthrottle_key_X / dp_xres; g_Config.fUnthrottleKeyY = (float)unthrottle_key_Y / dp_yres; + g_Config.fUnthrottleKeyScale = scale; } //L and R------------------------------------------------------------ @@ -358,6 +381,7 @@ void InitPadLayout() { if (g_Config.fLKeyX == -1.0 || g_Config.fLKeyY == -1.0 ) { g_Config.fLKeyX = (float)l_key_X / dp_xres; g_Config.fLKeyY = (float)l_key_Y / dp_yres; + g_Config.fLKeyScale = scale; } int r_key_X = dp_xres - 60 * scale; @@ -366,11 +390,10 @@ void InitPadLayout() { if (g_Config.fRKeyX == -1.0 || g_Config.fRKeyY == -1.0 ) { g_Config.fRKeyX = (float)r_key_X / dp_xres; g_Config.fRKeyY = (float)r_key_Y / dp_yres; + g_Config.fRKeyScale = scale; } }; - - UI::ViewGroup *CreatePadLayout(bool *pause) { //standard coord system @@ -380,93 +403,105 @@ UI::ViewGroup *CreatePadLayout(bool *pause) { //PSP buttons (triangle, circle, square, cross)--------------------- //space between the PSP buttons (traingle, circle, square and cross) - const int Action_button_spacing = g_Config.iActionButtonSpacing; + const float Action_button_scale = g_Config.fActionButtonScale; + const float Action_button_spacing = g_Config.fActionButtonSpacing * baseActionButtonSpacing; //position of the circle button (the PSP circle button). It is the farthest to the left - int Action_button_center_X = g_Config.fActionButtonCenterX * dp_xres; - int Action_button_center_Y = g_Config.fActionButtonCenterY * dp_yres; + float Action_button_center_X = g_Config.fActionButtonCenterX * dp_xres; + float Action_button_center_Y = g_Config.fActionButtonCenterY * dp_yres; - const int Action_circle_button_X = Action_button_center_X + Action_button_spacing; - const int Action_circle_button_Y = Action_button_center_Y; + const float Action_circle_button_X = Action_button_center_X + Action_button_spacing; + const float Action_circle_button_Y = Action_button_center_Y; - const int Action_cross_button_X = Action_button_center_X; - const int Action_cross_button_Y = Action_button_center_Y + Action_button_spacing; + const float Action_cross_button_X = Action_button_center_X; + const float Action_cross_button_Y = Action_button_center_Y + Action_button_spacing; - const int Action_triangle_button_X = Action_button_center_X; - const int Action_triangle_button_Y = Action_button_center_Y - Action_button_spacing; + const float Action_triangle_button_X = Action_button_center_X; + const float Action_triangle_button_Y = Action_button_center_Y - Action_button_spacing; - const int Action_square_button_X = Action_button_center_X - Action_button_spacing; - const int Action_square_button_Y = Action_button_center_Y; + const float Action_square_button_X = Action_button_center_X - Action_button_spacing; + const float Action_square_button_Y = Action_button_center_Y; //D-PAD (up down left right) (aka PSP cross)-------------------------------------------------------------- //radius to the D-pad - const int D_pad_Radius = g_Config.iDpadRadius; - int D_pad_X = g_Config.fDpadX * dp_xres; - int D_pad_Y = g_Config.fDpadY * dp_yres; + float D_pad_X = g_Config.fDpadX * dp_xres; + float D_pad_Y = g_Config.fDpadY * dp_yres; + float D_pad_scale = g_Config.fDpadScale; + float D_pad_spacing = g_Config.fDpadSpacing; //select, start, throttle-------------------------------------------- //space between the bottom keys (space between select, start and un-throttle) - int start_key_X = g_Config.fStartKeyX * dp_xres; - int start_key_Y = g_Config.fStartKeyY * dp_yres; + float start_key_X = g_Config.fStartKeyX * dp_xres; + float start_key_Y = g_Config.fStartKeyY * dp_yres; + float start_key_scale = g_Config.fStartKeyScale; - int select_key_X = g_Config.fSelectKeyX * dp_xres; - int select_key_Y = g_Config.fSelectKeyY * dp_yres; + float select_key_X = g_Config.fSelectKeyX * dp_xres; + float select_key_Y = g_Config.fSelectKeyY * dp_yres; + float select_key_scale = g_Config.fSelectKeyScale; - int unthrottle_key_X = g_Config.fUnthrottleKeyX * dp_xres; - int unthrottle_key_Y = g_Config.fUnthrottleKeyY * dp_yres; + float unthrottle_key_X = g_Config.fUnthrottleKeyX * dp_xres; + float unthrottle_key_Y = g_Config.fUnthrottleKeyY * dp_yres; + float unthrottle_key_scale = g_Config.fUnthrottleKeyScale; //L and R------------------------------------------------------------ - int l_key_X = g_Config.fLKeyX * dp_xres; - int l_key_Y = g_Config.fLKeyY * dp_yres; + float l_key_X = g_Config.fLKeyX * dp_xres; + float l_key_Y = g_Config.fLKeyY * dp_yres; + float l_key_scale = g_Config.fLKeyScale; - int r_key_X = g_Config.fRKeyX * dp_xres; - int r_key_Y = g_Config.fRKeyY * dp_yres; + float r_key_X = g_Config.fRKeyX * dp_xres; + float r_key_Y = g_Config.fRKeyY * dp_yres; + float r_key_scale = g_Config.fRKeyScale; - //analog stick------------------------------------------------------- - int analog_stick_X = g_Config.fAnalogStickX * dp_xres; - int analog_stick_Y = g_Config.fAnalogStickY * dp_yres; - + float analog_stick_X = g_Config.fAnalogStickX * dp_xres; + float analog_stick_Y = g_Config.fAnalogStickY * dp_yres; + float analog_stick_scale = g_Config.fAnalogStickScale; + const int halfW = dp_xres / 2; if (g_Config.bShowTouchControls) { - float scale = g_Config.fButtonScale; + int roundImage = g_Config.iTouchButtonStyle ? I_ROUND_LINE : I_ROUND; + int rectImage = g_Config.iTouchButtonStyle ? I_RECT_LINE : I_RECT; + int shoulderImage = g_Config.iTouchButtonStyle ? I_SHOULDER_LINE : I_SHOULDER; + int dirImage = g_Config.iTouchButtonStyle ? I_DIR_LINE : I_DIR; + int stickImage = g_Config.iTouchButtonStyle ? I_STICK_LINE : I_STICK; + int stickBg = g_Config.iTouchButtonStyle ? I_STICK_BG_LINE : I_STICK_BG; #if USE_PAUSE_BUTTON - root->Add(new BoolButton(pause, I_ROUND, I_ARROW, scale, new AnchorLayoutParams(halfW, 20, NONE, NONE, true)))->SetAngle(90); + root->Add(new BoolButton(pause, roundImage, I_ARROW, 1.0f, new AnchorLayoutParams(halfW, 20, NONE, NONE, true)))->SetAngle(90); #endif if (g_Config.bShowTouchCircle) - root->Add(new PSPButton(CTRL_CIRCLE, I_ROUND, I_CIRCLE, scale, new AnchorLayoutParams(Action_circle_button_X, Action_circle_button_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_CIRCLE, roundImage, I_CIRCLE, Action_button_scale, new AnchorLayoutParams(Action_circle_button_X, Action_circle_button_Y, NONE, NONE, true))); if (g_Config.bShowTouchCross) - root->Add(new PSPButton(CTRL_CROSS, I_ROUND, I_CROSS, scale, new AnchorLayoutParams(Action_cross_button_X, Action_cross_button_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_CROSS, roundImage, I_CROSS, Action_button_scale, new AnchorLayoutParams(Action_cross_button_X, Action_cross_button_Y, NONE, NONE, true))); if (g_Config.bShowTouchTriangle) - root->Add(new PSPButton(CTRL_TRIANGLE, I_ROUND, I_TRIANGLE, scale, new AnchorLayoutParams(Action_triangle_button_X, Action_triangle_button_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_TRIANGLE, roundImage, I_TRIANGLE, Action_button_scale, new AnchorLayoutParams(Action_triangle_button_X, Action_triangle_button_Y, NONE, NONE, true))); if (g_Config.bShowTouchSquare) - root->Add(new PSPButton(CTRL_SQUARE, I_ROUND, I_SQUARE, scale, new AnchorLayoutParams(Action_square_button_X, Action_square_button_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_SQUARE, roundImage, I_SQUARE, Action_button_scale, new AnchorLayoutParams(Action_square_button_X, Action_square_button_Y, NONE, NONE, true))); if (g_Config.bShowTouchStart) - root->Add(new PSPButton(CTRL_START, I_RECT, I_START, scale, new AnchorLayoutParams(start_key_X, start_key_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_START, rectImage, I_START, start_key_scale, new AnchorLayoutParams(start_key_X, start_key_Y, NONE, NONE, true))); if (g_Config.bShowTouchSelect) - root->Add(new PSPButton(CTRL_SELECT, I_RECT, I_SELECT, scale, new AnchorLayoutParams(select_key_X, select_key_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_SELECT, rectImage, I_SELECT, select_key_scale, new AnchorLayoutParams(select_key_X, select_key_Y, NONE, NONE, true))); if (g_Config.bShowTouchUnthrottle) - root->Add(new BoolButton(&PSP_CoreParameter().unthrottle, I_RECT, I_ARROW, scale, new AnchorLayoutParams(unthrottle_key_X, unthrottle_key_Y, NONE, NONE, true)))->SetAngle(180); + root->Add(new BoolButton(&PSP_CoreParameter().unthrottle, rectImage, I_ARROW, unthrottle_key_scale, new AnchorLayoutParams(unthrottle_key_X, unthrottle_key_Y, NONE, NONE, true)))->SetAngle(180); if (g_Config.bShowTouchLTrigger) - root->Add(new PSPButton(CTRL_LTRIGGER, I_SHOULDER, I_L, scale, new AnchorLayoutParams(l_key_X, l_key_Y, NONE, NONE, true))); + root->Add(new PSPButton(CTRL_LTRIGGER, shoulderImage, I_L, l_key_scale, new AnchorLayoutParams(l_key_X, l_key_Y, NONE, NONE, true))); if (g_Config.bShowTouchRTrigger) - root->Add(new PSPButton(CTRL_RTRIGGER, I_SHOULDER, I_R, scale, new AnchorLayoutParams(r_key_X,r_key_Y, NONE, NONE, true)))->FlipImageH(true); + root->Add(new PSPButton(CTRL_RTRIGGER, shoulderImage, I_R, r_key_scale, new AnchorLayoutParams(r_key_X,r_key_Y, NONE, NONE, true)))->FlipImageH(true); if (g_Config.bShowTouchDpad) - root->Add(new PSPCross(I_DIR, I_ARROW, scale, D_pad_Radius, new AnchorLayoutParams(D_pad_X, D_pad_Y, NONE, NONE, true))); + root->Add(new PSPDpad(dirImage, I_ARROW, D_pad_scale, D_pad_spacing, new AnchorLayoutParams(D_pad_X, D_pad_Y, NONE, NONE, true))); if (g_Config.bShowTouchAnalogStick) - root->Add(new PSPStick(I_STICKBG, I_STICK, 0, scale, new AnchorLayoutParams(analog_stick_X, analog_stick_Y, NONE, NONE, true))); + root->Add(new PSPStick(stickBg, stickImage, 0, analog_stick_scale, new AnchorLayoutParams(analog_stick_X, analog_stick_Y, NONE, NONE, true))); } return root; diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index a07448cba6..a28f64018b 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -75,9 +75,9 @@ private: int pspButtonBit_; }; -class PSPCross : public UI::View { +class PSPDpad : public UI::View { public: - PSPCross(int arrowIndex, int overlayIndex, float scale, float radius, UI::LayoutParams *layoutParams); + PSPDpad(int arrowIndex, int overlayIndex, float scale, float spacing, UI::LayoutParams *layoutParams); virtual void Key(const KeyInput &input) {} virtual void Update(const InputState &input) {} @@ -91,7 +91,7 @@ private: int overlayIndex_; float scale_; - float radius_; + float spacing_; int dragPointerId_; int down_; @@ -122,5 +122,9 @@ private: //initializes the layout from Config. if a default layout does not exist, //it sets up default values -void InitPadLayout(); +void InitPadLayout(float globalScale = 1.15f); UI::ViewGroup *CreatePadLayout(bool *pause); + +const int D_pad_Radius = 50; +const int baseActionButtonSpacing = 60; + diff --git a/UI/InstallZipScreen.cpp b/UI/InstallZipScreen.cpp new file mode 100644 index 0000000000..b01d223c81 --- /dev/null +++ b/UI/InstallZipScreen.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "base/logging.h" +#include "i18n/i18n.h" +#include "ui/ui.h" +#include "ui/view.h" +#include "ui/viewgroup.h" +#include "UI/ui_atlas.h" +#include "file/file_util.h" + +#include "Core/Util/GameManager.h" +#include "UI/InstallZipScreen.h" +#include "UI/MainScreen.h" + +void InstallZipScreen::CreateViews() { + using namespace UI; + + FileInfo fileInfo; + bool success = getFileInfo(zipPath_.c_str(), &fileInfo); + + I18NCategory *di = GetI18NCategory("Dialog"); + I18NCategory *iz = GetI18NCategory("InstallZip"); + + Margins actionMenuMargins(0, 100, 15, 0); + + root_ = new LinearLayout(ORIENT_HORIZONTAL); + + ViewGroup *leftColumn = new AnchorLayout(new LinearLayoutParams(1.0f)); + root_->Add(leftColumn); + + leftColumn->Add(new TextView(iz->T("Install game from ZIP file?"), ALIGN_LEFT, false, new AnchorLayoutParams(10, 10, NONE, NONE))); + leftColumn->Add(new TextView(zipPath_, ALIGN_LEFT, false, new AnchorLayoutParams(10, 60, NONE, NONE))); + + doneView_ = leftColumn->Add(new TextView("", new AnchorLayoutParams(10, 120, NONE, NONE))); + progressBar_ = leftColumn->Add(new ProgressBar(new AnchorLayoutParams(10, 200, 200, NONE))); + + ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); + root_->Add(rightColumnItems); + + installChoice_ = rightColumnItems->Add(new Choice(iz->T("Install"))); + installChoice_->OnClick.Handle(this, &InstallZipScreen::OnInstall); + backChoice_ = rightColumnItems->Add(new Choice(di->T("Back"))); + backChoice_->OnClick.Handle(this, &UIScreen::OnOK); // OK so that EmuScreen will handle it right + + rightColumnItems->Add(new CheckBox(&deleteZipFile_, iz->T("Delete ZIP file"))); +} + +void InstallZipScreen::key(const KeyInput &key) { + // Ignore all key presses during installation to avoid user escape + if (!g_GameManager.IsInstallInProgress()) { + UIScreen::key(key); + } +} + +UI::EventReturn InstallZipScreen::OnInstall(UI::EventParams ¶ms) { + if (g_GameManager.InstallGameOnThread(zipPath_, deleteZipFile_)) { + installStarted_ = true; + installChoice_->SetEnabled(false); + } + return UI::EVENT_DONE; +} + +void InstallZipScreen::update(InputState &input) { + I18NCategory *iz = GetI18NCategory("InstallZip"); + + using namespace UI; + if (g_GameManager.IsInstallInProgress()) { + progressBar_->SetVisibility(V_VISIBLE); + progressBar_->SetProgress(g_GameManager.GetCurrentInstallProgress()); + backChoice_->SetEnabled(false); + } else { + progressBar_->SetVisibility(V_GONE); + backChoice_->SetEnabled(true); + std::string err = g_GameManager.GetInstallError(); + if (!err.empty()) { + doneView_->SetText(iz->T(err.c_str())); + } else if (installStarted_) { + doneView_->SetText(iz->T("Installed!")); + MainScreen::showHomebrewTab = true; + } + } + UIScreen::update(input); +} diff --git a/UI/InstallZipScreen.h b/UI/InstallZipScreen.h new file mode 100644 index 0000000000..a4fb41960e --- /dev/null +++ b/UI/InstallZipScreen.h @@ -0,0 +1,46 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "base/functional.h" +#include "ui/view.h" +#include "ui/ui_screen.h" + +#include "UI/MiscScreens.h" + +class InstallZipScreen : public UIDialogScreenWithBackground { +public: + InstallZipScreen(std::string zipPath) : installChoice_(0), doneView_(0), zipPath_(zipPath), installStarted_(false), deleteZipFile_(false) {} + virtual void update(InputState &input); + virtual void key(const KeyInput &key); + +protected: + virtual void CreateViews(); + +private: + UI::EventReturn OnInstall(UI::EventParams ¶ms); + + UI::Choice *installChoice_; + UI::Choice *backChoice_; + UI::ProgressBar *progressBar_; + UI::TextView *doneView_; + std::string zipPath_; + bool installStarted_; + bool deleteZipFile_; +}; + diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 603422c557..f154c290b7 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -15,10 +15,15 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include +#include + #include "base/colorutil.h" #include "base/timeutil.h" +#include "file/path.h" #include "gfx_es2/draw_buffer.h" #include "math/curves.h" +#include "base/stringutil.h" #include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -36,11 +41,14 @@ #include "UI/CwCheatScreen.h" #include "UI/MiscScreens.h" #include "UI/ControlMappingScreen.h" +#include "UI/Store.h" #include "UI/ui_atlas.h" #include "Core/Config.h" #include "GPU/GPUInterface.h" #include "i18n/i18n.h" +#include "Core/HLE/sceUmd.h" + #ifdef _WIN32 #include "Windows/W32Util/ShellUtil.h" #include "Windows/WndMainWindow.h" @@ -54,10 +62,12 @@ #include +bool MainScreen::showHomebrewTab = false; + class GameButton : public UI::Clickable { public: GameButton(const std::string &gamePath, bool gridStyle, UI::LayoutParams *layoutParams = 0) - : UI::Clickable(layoutParams), gridStyle_(gridStyle), gamePath_(gamePath), holdFrameCount_(0) {} + : UI::Clickable(layoutParams), gridStyle_(gridStyle), gamePath_(gamePath), holdFrameCount_(0), holdEnabled_(true) {} virtual void Draw(UIContext &dc); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -71,14 +81,19 @@ public: } const std::string &GamePath() const { return gamePath_; } + + void SetHoldEnabled(bool hold) { + holdEnabled_ = hold; + } virtual void Touch(const TouchInput &input) { UI::Clickable::Touch(input); if (input.flags & TOUCH_UP) { holdFrameCount_ = 0; } } + virtual void Update(const InputState &input_state) { - if (down_) + if (down_ && holdEnabled_) holdFrameCount_++; else holdFrameCount_ = 0; @@ -98,8 +113,10 @@ public: private: bool gridStyle_; std::string gamePath_; + std::string title_; int holdFrameCount_; + bool holdEnabled_; }; void GameButton::Draw(UIContext &dc) { @@ -121,21 +138,21 @@ void GameButton::Draw(UIContext &dc) { style = dc.theme->itemDownStyle; if (!gridStyle_ || !texture) { - // w = 144 * 80 / 50; h = 50; if (HasFocus()) style = down_ ? dc.theme->itemDownStyle : dc.theme->itemFocusedStyle; + Drawable bg = style.background; + dc.Draw()->Flush(); dc.RebindTexture(); - dc.FillRect(style.background, bounds_); + dc.FillRect(bg, bounds_); dc.Draw()->Flush(); } if (texture) { color = whiteAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); shadowColor = blackAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); - float tw = texture->Width(); float th = texture->Height(); @@ -149,17 +166,23 @@ void GameButton::Draw(UIContext &dc) { int txOffset = down_ ? 4 : 0; if (!gridStyle_) txOffset = 0; + Bounds overlayBounds = bounds_; + u32 overlayColor = 0; + if (holdEnabled_) + overlayColor = whiteAlpha((holdFrameCount_ - 15) * 0.01f); + // Render button int dropsize = 10; if (texture) { if (txOffset) { dropsize = 3; y += txOffset * 2; + overlayBounds.y += txOffset * 2; } if (HasFocus()) { dc.Draw()->Flush(); dc.RebindTexture(); - dc.Draw()->DrawImage4Grid(I_DROP_SHADOW, x - dropsize*1.5f, y - dropsize*1.5f, x+w + dropsize*1.5f, y+h+dropsize*1.5f, alphaMul(color, 1.0f), 1.0f); + dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, x - dropsize*1.5f, y - dropsize*1.5f, x+w + dropsize*1.5f, y+h+dropsize*1.5f, alphaMul(color, 1.0f), 1.0f); dc.Draw()->Flush(); } else { dc.Draw()->Flush(); @@ -181,130 +204,125 @@ void GameButton::Draw(UIContext &dc) { dc.Draw()->Flush(); } + char discNumInfo[8]; + if (ginfo->disc_total > 1) + sprintf(discNumInfo, "-DISC%d", ginfo->disc_number); + else + strcpy(discNumInfo, ""); + dc.Draw()->Flush(); dc.RebindTexture(); dc.SetFontStyle(dc.theme->uiFont); if (!gridStyle_) { + float tw, th; dc.Draw()->Flush(); dc.PushScissor(bounds_); - dc.DrawText(ginfo->title.c_str(), bounds_.x + 150, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + if (title_.empty() && !ginfo->title.empty()) { + title_ = ReplaceAll(ginfo->title + discNumInfo, "&", "&&"); + title_ = ReplaceAll(title_, "\n", " "); + } + + dc.MeasureText(dc.GetFontStyle(), title_.c_str(), &tw, &th, 0); + + int availableWidth = bounds_.w - 150; + float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f; + + float tx = 150; + if (availableWidth < tw) { + tx -= (1.0f + sin(time_now_d() * 1.5f)) * sineWidth; + Bounds tb = bounds_; + tb.x = bounds_.x + 150; + tb.w = bounds_.w - 150; + dc.PushScissor(tb); + } + dc.DrawText(title_.c_str(), bounds_.x + tx, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + if (availableWidth < tw) { + dc.PopScissor(); + } dc.Draw()->Flush(); dc.PopScissor(); } else if (!texture) { dc.Draw()->Flush(); dc.PushScissor(bounds_); - dc.DrawText(ginfo->title.c_str(), bounds_.x + 4, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + dc.DrawText(title_.c_str(), bounds_.x + 4, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); dc.Draw()->Flush(); dc.PopScissor(); } else { dc.Draw()->Flush(); } + if (overlayColor) { + dc.FillRect(Drawable(overlayColor), overlayBounds); + } dc.RebindTexture(); } -// Abstraction above path that lets you navigate easily. -// "/" is a special path that means the root of the file system. On Windows, -// listing this will yield drives. -class PathBrowser { -public: - PathBrowser() {} - PathBrowser(std::string path) { SetPath(path); } - - void SetPath(const std::string &path); - void GetListing(std::vector &fileInfo, const char *filter = 0); - void Navigate(const std::string &path); - - std::string GetPath() { - if (path_ != "/") - return path_; - else - return ""; - } - std::string GetFriendlyPath() { - std::string str = GetPath(); - /* -#ifdef ANDROID - if (!memcmp(str.c_str(), g_Config.memCardDirectory.c_str(), g_Config.memCardDirectory.size())) - { - str = str.substr(g_Config.memCardDirectory.size()); - } -#endif*/ - return str; - } - - std::string path_; +enum GameBrowserFlags { + FLAG_HOMEBREWSTOREBUTTON = 1 }; -// Normalize slashes. -void PathBrowser::SetPath(const std::string &path) { - if (path[0] == '!') { - path_ = path; - return; + +class DirButton : public UI::Button { +public: + DirButton(std::string path, UI::LayoutParams *layoutParams) + : UI::Button(path, layoutParams) {} + + virtual void Draw(UIContext &dc); +}; + +void DirButton::Draw(UIContext &dc) { + Style style = dc.theme->buttonStyle; + + if (HasFocus()) style = dc.theme->buttonFocusedStyle; + if (down_) style = dc.theme->buttonDownStyle; + if (!IsEnabled()) style = dc.theme->buttonDisabledStyle; + + dc.FillRect(style.background, bounds_); + + const std::string text = GetText(); + + int image = I_FOLDER; + if (text == "..") { + image = I_UP_DIRECTORY; } - path_ = path; - for (size_t i = 0; i < path_.size(); i++) { - if (path_[i] == '\\') path_[i] = '/'; - } - if (!path_.size() || (path_[path_.size() - 1] != '/')) - path_ += "/"; -} + + float tw, th; + dc.MeasureText(dc.GetFontStyle(), text.c_str(), &tw, &th, 0); -void PathBrowser::GetListing(std::vector &fileInfo, const char *filter) { -#ifdef _WIN32 - if (path_ == "/") { - // Special path that means root of file system. - std::vector drives = getWindowsDrives(); - for (auto drive = drives.begin(); drive != drives.end(); ++drive) { - FileInfo fake; - fake.fullName = *drive; - fake.name = *drive; - fake.isDirectory = true; - fake.exists = true; - fake.size = 0; - fake.isWritable = false; - fileInfo.push_back(fake); - } - } -#endif + bool compact = bounds_.w < 180; - getFilesInDir(path_.c_str(), &fileInfo, filter); -} - -// TODO: Support paths like "../../hello" -void PathBrowser::Navigate(const std::string &path) { - if (path[0] == '!') - return; - - if (path == ".") - return; - if (path == "..") { - // Upwards. - // Check for windows drives. - if (path_.size() == 3 && path_[1] == ':') { - path_ = "/"; + if (compact) { + // No icon, except "up" + dc.PushScissor(bounds_); + if (image == I_FOLDER) { + dc.DrawText(text.c_str(), bounds_.x + 5, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); } else { - size_t slash = path_.rfind('/', path_.size() - 2); - if (slash != std::string::npos) - path_ = path_.substr(0, slash + 1); + dc.Draw()->DrawImage(image, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + } + dc.PopScissor(); + } else { + bool scissor = false; + if (tw + 150 > bounds_.w) { + dc.PushScissor(bounds_); + scissor = true; + } + + dc.Draw()->DrawImage(image, bounds_.x + 72, bounds_.centerY(), .88f, 0xFFFFFFFF, ALIGN_CENTER); + dc.DrawText(text.c_str(), bounds_.x + 150, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + + if (scissor) { + dc.PopScissor(); } - } - else { - if (path[1] == ':' && path_ == "/") - path_ = path; - else - path_ = path_ + path; - if (path_[path_.size() - 1] != '/') - path_ += "/"; } } class GameBrowser : public UI::LinearLayout { public: - GameBrowser(std::string path, bool allowBrowsing, bool *gridStyle_, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams = 0); + GameBrowser(std::string path, bool allowBrowsing, bool *gridStyle_, std::string lastText, std::string lastLink, int flags = 0, UI::LayoutParams *layoutParams = 0); UI::Event OnChoice; UI::Event OnHoldChoice; + UI::Choice *HomebrewStoreButton() { return homebrewStoreButton_; } private: void Refresh(); @@ -321,10 +339,12 @@ private: bool allowBrowsing_; std::string lastText_; std::string lastLink_; + int flags_; + UI::Choice *homebrewStoreButton_; }; -GameBrowser::GameBrowser(std::string path, bool allowBrowsing, bool *gridStyle, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams) - : LinearLayout(UI::ORIENT_VERTICAL, layoutParams), gameList_(0), path_(path), gridStyle_(gridStyle), allowBrowsing_(allowBrowsing), lastText_(lastText), lastLink_(lastLink) { +GameBrowser::GameBrowser(std::string path, bool allowBrowsing, bool *gridStyle, std::string lastText, std::string lastLink, int flags, UI::LayoutParams *layoutParams) + : LinearLayout(UI::ORIENT_VERTICAL, layoutParams), gameList_(0), path_(path), gridStyle_(gridStyle), allowBrowsing_(allowBrowsing), lastText_(lastText), lastLink_(lastLink), flags_(flags) { using namespace UI; Refresh(); } @@ -346,17 +366,18 @@ UI::EventReturn GameBrowser::HomeClick(UI::EventParams &e) { #elif defined(USING_QT_UI) I18NCategory *m = GetI18NCategory("MainMenu"); QString fileName = QFileDialog::getExistingDirectory(NULL, "Browse for Folder", g_Config.currentDirectory.c_str()); - if (QDir(fileName).exists()) { - g_Config.currentDirectory = fileName.toStdString(); - g_Config.Save(); + if (QDir(fileName).exists()) path_.SetPath(fileName.toStdString()); - } + else + return UI::EVENT_DONE; #elif defined(_WIN32) I18NCategory *m = GetI18NCategory("MainMenu"); std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), m->T("Choose folder")); if (!folder.size()) return UI::EVENT_DONE; path_.SetPath(folder); +#elif defined(BLACKBERRY) + path_.SetPath(std::string(getenv("PERIMETER_HOME")) + "/shared/misc"); #else path_.SetPath(getenv("HOME")); #endif @@ -369,21 +390,29 @@ UI::EventReturn GameBrowser::HomeClick(UI::EventParams &e) { void GameBrowser::Refresh() { using namespace UI; + homebrewStoreButton_ = 0; // Kill all the contents Clear(); - Add(new Spacer(5.0f)); + Add(new Spacer(1.0f)); I18NCategory *m = GetI18NCategory("MainMenu"); - if (allowBrowsing_) { + // No topbar on recent screen + if (path_.GetPath() != "!RECENT") { LinearLayout *topBar = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); - Margins pathMargins(5, 0); - topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER, true, new LinearLayoutParams(WRAP_CONTENT, FILL_PARENT, 1.0f, pathMargins))); -#if defined(_WIN32) - topBar->Add(new Choice(m->T("Browse", "Browse...")))->OnClick.Handle(this, &GameBrowser::HomeClick); + if (allowBrowsing_) { + topBar->Add(new Spacer(2.0f)); + Margins pathMargins(5, 0); + topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER, true, new LinearLayoutParams(1.0f))); +#if defined(_WIN32) || defined(USING_QT_UI) + topBar->Add(new Choice(m->T("Browse", "Browse...")))->OnClick.Handle(this, &GameBrowser::HomeClick); #else - topBar->Add(new Choice(m->T("Home")))->OnClick.Handle(this, &GameBrowser::HomeClick); + topBar->Add(new Choice(m->T("Home")))->OnClick.Handle(this, &GameBrowser::HomeClick); #endif + } else { + topBar->Add(new Spacer(new LinearLayoutParams(1.0f))); + } + ChoiceStrip *layoutChoice = topBar->Add(new ChoiceStrip(ORIENT_HORIZONTAL)); layoutChoice->AddChoice(I_GRID); layoutChoice->AddChoice(I_LINES); @@ -415,8 +444,9 @@ void GameBrowser::Refresh() { for (size_t i = 0; i < fileInfo.size(); i++) { if (fileInfo[i].isDirectory && (path_.GetPath().size() < 4 || !File::Exists(path_.GetPath() + fileInfo[i].name + "/EBOOT.PBP"))) { // Check if eboot directory - if (allowBrowsing_) - dirButtons.push_back(new UI::Button(fileInfo[i].name.c_str(), new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT))); + if (allowBrowsing_) { + dirButtons.push_back(new DirButton(fileInfo[i].name, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT))); + } } else { gameButtons.push_back(new GameButton(fileInfo[i].fullName, *gridStyle_, new UI::LinearLayoutParams(*gridStyle_ == true ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT))); } @@ -427,17 +457,25 @@ void GameBrowser::Refresh() { if (allowBrowsing_) { fileInfo.clear(); path_.GetListing(fileInfo, "zip:rar:r01:"); - for (size_t i = 0; i < fileInfo.size(); i++) { - if (!fileInfo[i].isDirectory) { - gameButtons.push_back(new GameButton(fileInfo[i].fullName, *gridStyle_, new UI::LinearLayoutParams(*gridStyle_ == true ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT))); + if (!fileInfo.empty()) { + UI::LinearLayout *zl = new UI::LinearLayout(UI::ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + zl->SetSpacing(4.0f); + Add(zl); + for (size_t i = 0; i < fileInfo.size(); i++) { + if (!fileInfo[i].isDirectory) { + GameButton *b = zl->Add(new GameButton(fileInfo[i].fullName, false, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT))); + b->OnClick.Handle(this, &GameBrowser::GameButtonClick); + b->SetHoldEnabled(false); + } } } } } - if (allowBrowsing_) - gameList_->Add(new UI::Button("..", new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)))-> + if (allowBrowsing_) { + gameList_->Add(new DirButton("..", new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)))-> OnClick.Handle(this, &GameBrowser::NavigateClick); + } for (size_t i = 0; i < dirButtons.size(); i++) { gameList_->Add(dirButtons[i])->OnClick.Handle(this, &GameBrowser::NavigateClick); @@ -449,6 +487,13 @@ void GameBrowser::Refresh() { b->OnHoldClick.Handle(this, &GameBrowser::GameButtonHoldClick); } + if (g_Config.bHomebrewStore && (flags_ & FLAG_HOMEBREWSTOREBUTTON)) { + Add(new Spacer()); + homebrewStoreButton_ = Add(new Choice(m->T("DownloadFromStore", "Download from the PPSSPP Homebrew Store"), new UI::LinearLayoutParams(UI::WRAP_CONTENT, UI::WRAP_CONTENT))); + } else { + homebrewStoreButton_ = 0; + } + if (!lastText_.empty() && gameButtons.empty()) { Add(new Spacer()); Add(new Choice(lastText_, new UI::LinearLayoutParams(UI::WRAP_CONTENT, UI::WRAP_CONTENT)))->OnClick.Handle(this, &GameBrowser::LastClick); @@ -482,6 +527,10 @@ UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) { return UI::EVENT_DONE; } +MainScreen::MainScreen() : backFromStore_(false) { + System_SendMessage("event", "mainscreen"); +} + void MainScreen::CreateViews() { // Information in the top left. // Back button to the bottom left. @@ -496,6 +545,7 @@ void MainScreen::CreateViews() { Margins actionMenuMargins(0, 10, 10, 0); TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64); + tabHolder_ = leftColumn; leftColumn->SetClip(true); ScrollView *scrollRecentGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); @@ -503,16 +553,21 @@ void MainScreen::CreateViews() { ScrollView *scrollHomebrew = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); GameBrowser *tabRecentGames = new GameBrowser( - "!RECENT", false, &g_Config.bGridView1, "", "", + "!RECENT", false, &g_Config.bGridView1, "", "", 0, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true, &g_Config.bGridView2, - m->T("How to get games"), "http://www.ppsspp.org/getgames.html", + GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true, &g_Config.bGridView2, + m->T("How to get games"), "http://www.ppsspp.org/getgames.html", 0, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); GameBrowser *tabHomebrew = new GameBrowser(GetSysDirectory(DIRECTORY_GAME), false, &g_Config.bGridView3, - m->T("How to get homebrew & demos"), "http://www.ppsspp.org/gethomebrew.html", + m->T("How to get homebrew & demos", "How to get homebrew && demos"), "http://www.ppsspp.org/gethomebrew.html", + FLAG_HOMEBREWSTOREBUTTON, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - + Choice *hbStore = tabHomebrew->HomebrewStoreButton(); + if (hbStore) { + hbStore->OnClick.Handle(this, &MainScreen::OnHomebrewStore); + } + scrollRecentGames->Add(tabRecentGames); scrollAllGames->Add(tabAllGames); scrollHomebrew->Add(tabHomebrew); @@ -528,20 +583,24 @@ void MainScreen::CreateViews() { tabAllGames->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected); tabHomebrew->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected); - if (g_Config.recentIsos.size() > 0) { leftColumn->SetCurrentTab(0); - }else{ + } else { leftColumn->SetCurrentTab(1); } -/* - if (info) { + + if (backFromStore_ || showHomebrewTab) { + leftColumn->SetCurrentTab(2); + backFromStore_ = false; + showHomebrewTab = false; + } + +/* if (info) { texvGameIcon_ = leftColumn->Add(new TextureView(0, IS_DEFAULT, new AnchorLayoutParams(144 * 2, 80 * 2, 10, 10, NONE, NONE))); tvTitle_ = leftColumn->Add(new TextView(0, info->title, ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 200, NONE, NONE))); tvGameSize_ = leftColumn->Add(new TextView(0, "...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 250, NONE, NONE))); tvSaveDataSize_ = leftColumn->Add(new TextView(0, "...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 290, NONE, NONE))); - } - */ + } */ ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL); LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); @@ -553,7 +612,7 @@ void MainScreen::CreateViews() { rightColumnItems->SetSpacing(0.0f); LinearLayout *logos = new LinearLayout(ORIENT_HORIZONTAL); #ifdef GOLD - logos->Add(new ImageView(I_ICONGOLD, new AnchorLayoutParams(64, 64, 10, 10, NONE, NONE, false))); + logos->Add(new ImageView(I_ICONGOLD, IS_DEFAULT, new AnchorLayoutParams(64, 64, 10, 10, NONE, NONE, false))); #else logos->Add(new ImageView(I_ICON, IS_DEFAULT, new AnchorLayoutParams(64, 64, 10, 10, NONE, NONE, false))); #endif @@ -574,6 +633,7 @@ void MainScreen::CreateViews() { gold->SetIcon(I_ICONGOLD); #endif rightColumnItems->Add(new Choice(m->T("Exit")))->OnClick.Handle(this, &MainScreen::OnExit); + if (vertical) { root_ = new LinearLayout(ORIENT_VERTICAL); rightColumn->ReplaceLayoutParams(new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); @@ -587,6 +647,49 @@ void MainScreen::CreateViews() { root_->Add(leftColumn); root_->Add(rightColumn); } + + I18NCategory *u = GetI18NCategory("Upgrade"); + + upgradeBar_ = 0; + if (!g_Config.upgradeMessage.empty()) { + upgradeBar_ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + + UI::Margins textMargins(10, 5); + UI::Margins buttonMargins(0, 0); + UI::Drawable solid(0xFFbd9939); + upgradeBar_->SetBG(solid); + upgradeBar_->Add(new TextView(u->T("New version of PPSSPP available") + std::string(": ") + g_Config.upgradeVersion, new LinearLayoutParams(1.0f, textMargins))); + upgradeBar_->Add(new Button(u->T("Download"), new LinearLayoutParams(buttonMargins)))->OnClick.Handle(this, &MainScreen::OnDownloadUpgrade); + upgradeBar_->Add(new Button(u->T("Dismiss"), new LinearLayoutParams(buttonMargins)))->OnClick.Handle(this, &MainScreen::OnDismissUpgrade); + + // Slip in under root_ + LinearLayout *newRoot = new LinearLayout(ORIENT_VERTICAL); + newRoot->Add(root_); + newRoot->Add(upgradeBar_); + root_->ReplaceLayoutParams(new LinearLayoutParams(1.0)); + root_ = newRoot; + } +} + +UI::EventReturn MainScreen::OnDownloadUpgrade(UI::EventParams &e) { +#ifdef ANDROID + // Go to app store +#ifdef GOLD + LaunchBrowser("market://details?id=org.ppsspp.ppssppgold"); +#else + LaunchBrowser("market://details?id=org.ppsspp.ppsspp"); +#endif +#else + // Go directly to ppsspp.org and let the user sort it out + LaunchBrowser("http://www.ppsspp.org/downloads.html"); +#endif + return EVENT_DONE; +} + +UI::EventReturn MainScreen::OnDismissUpgrade(UI::EventParams &e) { + g_Config.DismissUpgrade(); + upgradeBar_->SetVisibility(V_GONE); + return EVENT_DONE; } void MainScreen::sendMessage(const char *message, const char *value) { @@ -612,8 +715,8 @@ void MainScreen::update(InputState &input) { } UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) { -#if defined(USING_QT_UI) && !defined(MEEGO_EDITION_HARMATTAN) - QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf)"); +#if defined(USING_QT_UI) + QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip)"); if (QFile::exists(fileName)) { QDir newPath; g_Config.currentDirectory = newPath.filePath(fileName).toStdString(); @@ -668,6 +771,11 @@ UI::EventReturn MainScreen::OnCredits(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn MainScreen::OnHomebrewStore(UI::EventParams &e) { + screenManager()->push(new StoreScreen()); + return UI::EVENT_DONE; +} + UI::EventReturn MainScreen::OnSupport(UI::EventParams &e) { #ifdef ANDROID LaunchBrowser("market://details?id=org.ppsspp.ppssppgold"); @@ -688,11 +796,19 @@ UI::EventReturn MainScreen::OnForums(UI::EventParams &e) { } UI::EventReturn MainScreen::OnExit(UI::EventParams &e) { + System_SendMessage("event", "exitprogram"); NativeShutdown(); exit(0); return UI::EVENT_DONE; } +void MainScreen::dialogFinished(const Screen *dialog, DialogResult result) { + if (dialog->tag() == "store") { + backFromStore_ = true; + RecreateViews(); + } +} + void GamePauseScreen::update(InputState &input) { UpdateUIState(UISTATE_PAUSEMENU); UIScreen::update(input); @@ -715,11 +831,11 @@ void GamePauseScreen::DrawBackground(UIContext &dc) { } if (hasPic) { uint32_t color = whiteAlpha(ease((time_now_d() - ginfo->timePic1WasLoaded) * 3)) & 0xFFc0c0c0; - dc.Draw()->DrawTexRect(0,0,dp_xres, dp_yres, 0,0,1,1,color); + dc.Draw()->DrawTexRect(0,0,dp_xres, dp_yres, 0,0,1,1, color); dc.Flush(); dc.RebindTexture(); } else { - ::DrawBackground(1.0f); + ::DrawBackground(1.0f); dc.RebindTexture(); dc.Flush(); } @@ -734,7 +850,7 @@ GamePauseScreen::~GamePauseScreen() { } void GamePauseScreen::CreateViews() { - static const int NUM_SAVESLOTS = 5; + static const int NUM_SAVESLOTS = 5; using namespace UI; Margins actionMenuMargins(0, 100, 15, 0); @@ -783,6 +899,9 @@ void GamePauseScreen::CreateViews() { rightColumn->Add(rightColumnItems); rightColumnItems->SetSpacing(0.0f); + if (getUMDReplacePermit()) { + rightColumnItems->Add(new Choice(i->T("Switch UMD")))->OnClick.Handle(this, &GamePauseScreen::OnSwitchUMD); + } rightColumnItems->Add(new Choice(i->T("Continue")))->OnClick.Handle(this, &UIScreen::OnBack); rightColumnItems->Add(new Choice(i->T("Game Settings")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings); if (g_Config.bEnableCheats) { @@ -843,6 +962,11 @@ UI::EventReturn GamePauseScreen::OnCwCheat(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn GamePauseScreen::OnSwitchUMD(UI::EventParams &e) { + screenManager()->push(new UmdReplaceScreen()); + return UI::EVENT_DONE; +} + void GamePauseScreen::sendMessage(const char *message, const char *value) { // Since the language message isn't allowed to be in native, we have to have add this // to every screen which directly inherits from UIScreen(which are few right now, luckily). @@ -850,3 +974,77 @@ void GamePauseScreen::sendMessage(const char *message, const char *value) { screenManager()->RecreateAllViews(); } } + +void UmdReplaceScreen::CreateViews() { + Margins actionMenuMargins(0, 100, 15, 0); + I18NCategory *m = GetI18NCategory("MainMenu"); + I18NCategory *d = GetI18NCategory("Dialog"); + + TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(1.0)); + leftColumn->SetClip(true); + + ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(270, FILL_PARENT, actionMenuMargins)); + LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + rightColumnItems->SetSpacing(0.0f); + rightColumn->Add(rightColumnItems); + + ScrollView *scrollRecentGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + ScrollView *scrollAllGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); + + GameBrowser *tabRecentGames = new GameBrowser( + "!RECENT", false, &g_Config.bGridView1, "", "", 0, + new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true, &g_Config.bGridView2, + m->T("How to get games"), "http://www.ppsspp.org/getgames.html", 0, + new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + + scrollRecentGames->Add(tabRecentGames); + scrollAllGames->Add(tabAllGames); + + leftColumn->AddTab(m->T("Recent"), scrollRecentGames); + leftColumn->AddTab(m->T("Games"), scrollAllGames); + + tabRecentGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelectedInstant); + tabAllGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelectedInstant); + tabRecentGames->OnHoldChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); + tabAllGames->OnHoldChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); + + rightColumnItems->Add(new Choice(d->T("Cancel")))->OnClick.Handle(this, &UmdReplaceScreen::OnCancel); + rightColumnItems->Add(new Choice(m->T("Game Settings")))->OnClick.Handle(this, &UmdReplaceScreen::OnGameSettings); + + if (g_Config.recentIsos.size() > 0) { + leftColumn->SetCurrentTab(0); + }else{ + leftColumn->SetCurrentTab(1); + } + + root_ = new LinearLayout(ORIENT_HORIZONTAL); + root_->Add(leftColumn); + root_->Add(rightColumn); +} + +void UmdReplaceScreen::update(InputState &input) { + UpdateUIState(UISTATE_PAUSEMENU); + UIScreen::update(input); +} + +UI::EventReturn UmdReplaceScreen::OnGameSelected(UI::EventParams &e) { + __UmdReplace(e.s); + screenManager()->finishDialog(this, DR_OK); + return UI::EVENT_DONE; +} + +UI::EventReturn UmdReplaceScreen:: OnCancel(UI::EventParams &e) { + screenManager()->finishDialog(this, DR_CANCEL); + return UI::EVENT_DONE; +} + +UI::EventReturn UmdReplaceScreen:: OnGameSettings(UI::EventParams &e) { + screenManager()->push(new GameSettingsScreen("")); + return UI::EVENT_DONE; +} +UI::EventReturn UmdReplaceScreen:: OnGameSelectedInstant(UI::EventParams &e) { + __UmdReplace(e.s); + screenManager()->finishDialog(this, DR_OK); + return UI::EVENT_DONE; +} diff --git a/UI/MainScreen.h b/UI/MainScreen.h index 4ea4f5ef9f..01080a155a 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -28,14 +28,18 @@ class MainScreen : public UIScreenWithBackground { public: - MainScreen() {} + MainScreen(); virtual bool isTopLevel() const { return true; } + // Horrible hack to show the demos & homebrew tab after having installed a game from a zip file. + static bool showHomebrewTab; + protected: virtual void CreateViews(); virtual void update(InputState &input); virtual void sendMessage(const char *message, const char *value); + virtual void dialogFinished(const Screen *dialog, DialogResult result); private: UI::EventReturn OnGameSelected(UI::EventParams &e); @@ -49,6 +53,14 @@ private: UI::EventReturn OnPPSSPPOrg(UI::EventParams &e); UI::EventReturn OnForums(UI::EventParams &e); UI::EventReturn OnExit(UI::EventParams &e); + UI::EventReturn OnDownloadUpgrade(UI::EventParams &e); + UI::EventReturn OnDismissUpgrade(UI::EventParams &e); + UI::EventReturn OnHomebrewStore(UI::EventParams &e); + + UI::LinearLayout *upgradeBar_; + UI::TabHolder *tabHolder_; + + bool backFromStore_; }; class GamePauseScreen : public UIDialogScreen { @@ -73,14 +85,31 @@ private: UI::EventReturn OnLoadState(UI::EventParams &e); UI::EventReturn OnRewind(UI::EventParams &e); - UI::EventReturn OnLanguageChange(UI::EventParams &e); - UI::EventReturn OnStateSelected(UI::EventParams &e); UI::EventReturn OnCwCheat(UI::EventParams &e); + UI::EventReturn OnSwitchUMD(UI::EventParams &e); + std::string gamePath_; UI::ChoiceStrip *saveSlots_; UI::Choice *saveStateButton_; UI::Choice *loadStateButton_; }; + +class UmdReplaceScreen : public UIDialogScreenWithBackground { +public: + UmdReplaceScreen() {} + +protected: + virtual void CreateViews(); + virtual void update(InputState &input); + //virtual void sendMessage(const char *message, const char *value); + +private: + UI::EventReturn OnGameSelected(UI::EventParams &e); + UI::EventReturn OnGameSelectedInstant(UI::EventParams &e); + + UI::EventReturn OnCancel(UI::EventParams &e); + UI::EventReturn OnGameSettings(UI::EventParams &e); +}; diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index b17c6479dd..6224795221 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -83,7 +83,11 @@ void DrawBackground(float alpha) { glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(0.1f,0.2f,0.43f,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - ui_draw2d.DrawImageStretch(I_BG, 0, 0, dp_xres, dp_yres); + int img = I_BG; +#ifdef GOLD + img = I_BG_GOLD; +#endif + ui_draw2d.DrawImageStretch(img, 0, 0, dp_xres, dp_yres); float t = time_now(); for (int i = 0; i < 100; i++) { float x = xbase[i]; @@ -192,13 +196,14 @@ UI::EventReturn PromptScreen::OnNo(UI::EventParams &e) { } PostProcScreen::PostProcScreen(const std::string &title) : ListPopupScreen(title) { + I18NCategory *ps = GetI18NCategory("PostShaders"); shaders_ = GetAllPostShaderInfo(); std::vector items; int selected = -1; for (int i = 0; i < (int)shaders_.size(); i++) { if (shaders_[i].section == g_Config.sPostShaderName) selected = i; - items.push_back(shaders_[i].name); + items.push_back(ps->T(shaders_[i].name.c_str())); } adaptor_ = UI::StringVectorListAdaptor(items, selected); } @@ -230,7 +235,7 @@ NewLanguageScreen::NewLanguageScreen(const std::string &title) : ListPopupScreen if (tempLangs[i].name.find("README") != std::string::npos) { continue; } - + #ifndef _WIN32 // ar_AE only works on Windows. if (tempLangs[i].name.find("ar_AE") != std::string::npos) { @@ -268,7 +273,6 @@ void NewLanguageScreen::OnCompleted(DialogResult result) { if (result != DR_OK) return; std::string oldLang = g_Config.sLanguageIni; - std::string iniFile = langs_[listView_->GetSelected()].name; size_t dot = iniFile.find('.'); @@ -280,7 +284,7 @@ void NewLanguageScreen::OnCompleted(DialogResult result) { return; g_Config.sLanguageIni = code; - + if (i18nrepo.LoadIni(g_Config.sLanguageIni)) { // Dunno what else to do here. if (langValuesMapping.find(code) == langValuesMapping.end()) { @@ -383,8 +387,11 @@ void CreditsScreen::CreateViews() { root_->Add(new Button(c->T("PPSSPP Forums"), new AnchorLayoutParams(260, 64, 10, NONE, NONE, 84, false)))->OnClick.Handle(this, &CreditsScreen::OnForums); root_->Add(new Button("www.ppsspp.org", new AnchorLayoutParams(260, 64, 10, NONE, NONE, 158, false)))->OnClick.Handle(this, &CreditsScreen::OnPPSSPPOrg); } +#ifdef ANDROID + root_->Add(new Button(c->T("Share PPSSPP"), new AnchorLayoutParams(260, 64, NONE, NONE, 10, 84, false)))->OnClick.Handle(this, &CreditsScreen::OnShare); +#endif #ifdef GOLD - root_->Add(new ImageView(I_ICONGOLD, new AnchorLayoutParams(100, 64, 10, 10, NONE, NONE, false))); + root_->Add(new ImageView(I_ICONGOLD, IS_DEFAULT, new AnchorLayoutParams(100, 64, 10, 10, NONE, NONE, false))); #else root_->Add(new ImageView(I_ICON, IS_DEFAULT, new AnchorLayoutParams(100, 64, 10, 10, NONE, NONE, false))); #endif @@ -414,6 +421,12 @@ UI::EventReturn CreditsScreen::OnChineseForum(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn CreditsScreen::OnShare(UI::EventParams &e) { + I18NCategory *c = GetI18NCategory("PSPCredits"); + System_SendMessage("sharetext", c->T("CheckOutPPSSPP", "Check out PPSSPP, the awesome PSP emulator: http://www.ppsspp.org/")); + return UI::EVENT_DONE; +} + UI::EventReturn CreditsScreen::OnOK(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; @@ -478,6 +491,9 @@ void CreditsScreen::render() { "kaienfr", "shenweip", "Danyal Zia", + "Igor Calabria", + "Coldbird", + "Kyhel", "", "", c->T("specialthanks", "Special thanks to:"), diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h index c0c0592c16..3ac74d3c5e 100644 --- a/UI/MiscScreens.h +++ b/UI/MiscScreens.h @@ -108,6 +108,7 @@ public: CreditsScreen() : frames_(0) {} void update(InputState &input); void render(); + virtual void CreateViews(); private: @@ -117,6 +118,7 @@ private: UI::EventReturn OnPPSSPPOrg(UI::EventParams &e); UI::EventReturn OnForums(UI::EventParams &e); UI::EventReturn OnChineseForum(UI::EventParams &e); + UI::EventReturn OnShare(UI::EventParams &e); int frames_; }; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e8a66ff2ca..5ef50f1d95 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -28,15 +28,18 @@ // in NativeShutdown. #include +#ifdef _WIN32 +#include +#include "ext/jpge/jpge.h" +#endif #include "base/logging.h" #include "base/mutex.h" #include "base/NativeApp.h" #include "file/vfs.h" #include "file/zip_read.h" -#include "native/ext/stb_image_write/stb_image_writer.h" -#include "native/ext/jpge/jpge.h" -#include "native/util/text/utf8.h" +#include "thread/thread.h" +#include "net/http_client.h" #include "gfx_es2/gl_state.h" #include "gfx_es2/draw_text.h" #include "gfx_es2/draw_buffer.h" @@ -50,6 +53,7 @@ #include "ui/screen.h" #include "ui/ui_context.h" #include "ui/view.h" +#include "util/text/utf8.h" #include "Common/FileUtil.h" #include "Common/LogManager.h" @@ -59,6 +63,7 @@ #include "Core/HLE/sceCtrl.h" #include "Core/Host.h" #include "Core/SaveState.h" +#include "Core/Util/GameManager.h" #include "Common/MemArena.h" #include "ui_atlas.h" @@ -78,12 +83,10 @@ static UI::Theme ui_theme; #include "../../android/jni/ArmEmitterTest.h" #endif -#if defined(__APPLE__) && !defined(IOS) -#include -#endif - #ifdef IOS #include "ios/iOSCoreAudio.h" +#elif defined(__APPLE__) +#include #endif // https://github.com/richq/android-ndk-profiler @@ -99,7 +102,7 @@ std::string config_filename; std::string game_title; #ifdef IOS -bool isJailed; +bool iosCanUseJit; #endif // Really need to clean this mess of globals up... but instead I add more :P @@ -187,28 +190,24 @@ std::string boot_filename = ""; void NativeHost::InitSound(PMixer *mixer) { g_mixer = mixer; - #ifdef IOS - iOSCoreAudioInit(); + iOSCoreAudioInit(); #endif } void NativeHost::ShutdownSound() { #ifdef IOS - iOSCoreAudioShutdown(); + iOSCoreAudioShutdown(); #endif - g_mixer = 0; } int NativeMix(short *audio, int num_samples) { - // ILOG("Entering mixer"); if (g_mixer) { num_samples = g_mixer->Mix(audio, num_samples); } else { memset(audio, 0, num_samples * 2 * sizeof(short)); } - // ILOG("Leaving mixer"); return num_samples; } @@ -222,28 +221,6 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo #endif } -const std::string NativeProgramPath() { -#if (defined(__APPLE__) && !defined(IOS)) || defined(__linux__) - char program_path[4096]; - uint32_t program_path_size = sizeof(program_path) - 1; -#if defined(__linux__) - if (readlink("/proc/self/exe", program_path, 4095) > 0) { -#elif defined(__APPLE__) && !defined(IOS) - if (_NSGetExecutablePath(program_path, &program_path_size) == 0) { -#else -#error Unmatched ifdef. -#endif - program_path[sizeof(program_path) - 1] = '\0'; - char *last_slash = strrchr(program_path, '/'); - if (last_slash != NULL) - *(last_slash + 1) = '\0'; - return program_path; - } -#endif - - return ""; -} - void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID) { #ifdef ANDROID_NDK_PROFILER @@ -260,22 +237,19 @@ void NativeInit(int argc, const char *argv[], #ifdef IOS user_data_path += "/"; -#elif defined(__APPLE__) - if (File::Exists(NativeProgramPath() + "assets")) - VFSRegister("", new DirectoryAssetReader((NativeProgramPath() + "assets/").c_str())); - // It's common to be in a build-xyz/ directory. - else - VFSRegister("", new DirectoryAssetReader((NativeProgramPath() + "../assets/").c_str())); #endif // We want this to be FIRST. -#ifndef USING_QT_UI -#if defined(BLACKBERRY) || defined(IOS) +#ifdef USING_QT_UI + VFSRegister("", new AssetsAssetReader()); +#elif defined(BLACKBERRY) || defined(IOS) // Packed assets are included in app VFSRegister("", new DirectoryAssetReader(external_directory)); +#elif defined(__APPLE__) || (defined(__linux__) && !defined(ANDROID)) + VFSRegister("", new DirectoryAssetReader((File::GetExeDirectory() + "assets/").c_str())); + VFSRegister("", new DirectoryAssetReader((File::GetExeDirectory()).c_str())); #else VFSRegister("", new DirectoryAssetReader("assets/")); -#endif #endif VFSRegister("", new DirectoryAssetReader(savegame_directory)); @@ -292,15 +266,13 @@ void NativeInit(int argc, const char *argv[], g_Config.memCardDirectory = user_data_path; g_Config.flash0Directory = std::string(external_directory) + "/flash0/"; #elif !defined(_WIN32) - g_Config.memCardDirectory = std::string(getenv("HOME")) + "/.ppsspp/"; - std::string program_path = NativeProgramPath(); - if (program_path.empty()) - g_Config.flash0Directory = g_Config.memCardDirectory + "/flash0/"; - else if (File::Exists(program_path + "flash0")) - g_Config.flash0Directory = program_path + "flash0/"; - // It's common to be in a build-xyz/ directory. - else - g_Config.flash0Directory = program_path + "../flash0/"; + char* config = getenv("XDG_CONFIG_HOME"); + if (!config) { + config = getenv("HOME"); + strcat(config, "/.config"); + } + g_Config.memCardDirectory = std::string(config) + "/ppsspp/"; + g_Config.flash0Directory = File::GetExeDirectory() + "/flash0/"; #endif #ifndef _WIN32 @@ -308,7 +280,6 @@ void NativeInit(int argc, const char *argv[], LogManager::Init(); LogManager *logman = LogManager::GetInstance(); - ILOG("Logman: %p", logman); g_Config.AddSearchPath(user_data_path); g_Config.AddSearchPath(g_Config.memCardDirectory + "PSP/SYSTEM/"); @@ -319,7 +290,7 @@ void NativeInit(int argc, const char *argv[], #ifdef ANDROID // On Android, create a PSP directory tree in the external_directory, - // to hopefully reduce confusion a bit. + // to hopefully reduce confusion a bit. ILOG("Creating %s", (g_Config.memCardDirectory + "PSP").c_str()); mkDir((g_Config.memCardDirectory + "PSP").c_str()); mkDir((g_Config.memCardDirectory + "PSP/SAVEDATA").c_str()); @@ -398,20 +369,15 @@ void NativeInit(int argc, const char *argv[], logman->AddListener(type, logger); #endif } -#ifdef __SYMBIAN32__ - g_Config.bSeparateCPUThread = false; - g_Config.bSeparateIOThread = false; -#endif // Special hack for G3D as it's very spammy. Need to make a flag for this. if (!gfxLog) logman->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); - INFO_LOG(BOOT, "Logger inited."); -#endif +#endif i18nrepo.LoadIni(g_Config.sLanguageIni); I18NCategory *d = GetI18NCategory("DesktopUI"); - // Note to translators: do not translate this/add this to PPSSPP-lang's files. - // It's intended to be custom for every user. + // Note to translators: do not translate this/add this to PPSSPP-lang's files. + // It's intended to be custom for every user. // Only add it to your own personal copies of PPSSPP. #ifdef _WIN32 // TODO: Could allow a setting to specify a font file to load? @@ -425,9 +391,7 @@ void NativeInit(int argc, const char *argv[], g_gameInfoCache.Init(); - screenManager = new ScreenManager(); - if (skipLogo) { screenManager->switchScreen(new EmuScreen(boot_filename)); } else { @@ -493,6 +457,16 @@ void NativeInitGraphics() { ui_theme.buttonHighlightedStyle = ui_theme.itemHighlightedStyle; ui_theme.popupTitle.fgColor = 0xFFE3BE59; + +#ifdef GOLD + ui_theme.itemFocusedStyle.background = UI::Drawable(0xFF4cc2ed); + ui_theme.itemDownStyle.background = UI::Drawable(0xFF39a9ee); + ui_theme.itemDisabledStyle.background = UI::Drawable(0x55AFD4E0); + ui_theme.itemHighlightedStyle.background = UI::Drawable(0x5539BBbd); + + ui_theme.popupTitle.fgColor = 0xFF59BEE3; +#endif + ui_draw2d.Init(); ui_draw2d_front.Init(); @@ -538,8 +512,8 @@ void NativeShutdownGraphics() { } void TakeScreenshot() { -#ifdef _WIN32 g_TakeScreenshot = false; +#ifdef _WIN32 mkDir(g_Config.memCardDirectory + "/PSP/SCREENSHOT"); // First, find a free filename. @@ -558,23 +532,29 @@ void TakeScreenshot() { } // Okay, allocate a buffer. - u8 *buffer = new u8[4 * pixel_xres * pixel_yres]; + u8 *buffer = new u8[3 * pixel_xres * pixel_yres]; // Silly openGL reads upside down, we flip to another buffer for simplicity. - u8 *flipbuffer = new u8[4 * pixel_xres * pixel_yres]; + u8 *flipbuffer = new u8[3 * pixel_xres * pixel_yres]; - glReadPixels(0, 0, pixel_xres, pixel_yres, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + glReadPixels(0, 0, pixel_xres, pixel_yres, GL_RGB, GL_UNSIGNED_BYTE, buffer); for (int y = 0; y < pixel_yres; y++) { - memcpy(flipbuffer + y * pixel_xres * 4, buffer + (pixel_yres - y - 1) * pixel_xres * 4, pixel_xres * 4); + memcpy(flipbuffer + y * pixel_xres * 3, buffer + (pixel_yres - y - 1) * pixel_xres * 3, pixel_xres * 3); } - if(g_Config.bScreenshotsAsPNG) - stbi_write_png(temp, pixel_xres, pixel_yres, 4, flipbuffer, pixel_xres * 4); - else - { + if (g_Config.bScreenshotsAsPNG) { + png_image png; + memset(&png, 0, sizeof(png)); + png.version = PNG_IMAGE_VERSION; + png.format = PNG_FORMAT_RGB; + png.width = pixel_xres; + png.height = pixel_yres; + png_image_write_to_file(&png, temp, 0, flipbuffer, pixel_xres * 3, NULL); + png_image_free(&png); + } else { jpge::params params; params.m_quality = 90; - compress_image_to_jpeg_file(temp, pixel_xres, pixel_yres, 4, flipbuffer, params); + compress_image_to_jpeg_file(temp, pixel_xres, pixel_yres, 3, flipbuffer, params); } delete [] buffer; @@ -584,12 +564,40 @@ void TakeScreenshot() { #endif } +void DrawDownloadsOverlay(UIContext &ctx) { + // Thin bar at the top of the screen like Chrome. + std::vector progress = g_DownloadManager.GetCurrentProgress(); + if (progress.empty()) { + return; + } + + static const uint32_t colors[4] = { + 0xFFFFFFFF, + 0xFFCCCCCC, + 0xFFAAAAAA, + 0xFF777777, + }; + + ctx.Begin(); + int h = 5; + for (size_t i = 0; i < progress.size(); i++) { + float barWidth = 10 + (dp_xres - 10) * progress[i]; + Bounds bounds(0, h * i, barWidth, h); + UI::Drawable solid(colors[i & 3]); + ctx.FillRect(solid, bounds); + } + ctx.End(); + ctx.Flush(); +} + void NativeRender() { + g_GameManager.Update(); + glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Clearing the screen at the start of the frame is an optimization for tiled mobile GPUs, as it then doesn't need to keep it around between frames. - glClearColor(0,0,0,1); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glstate.viewport.set(0, 0, pixel_xres, pixel_yres); @@ -601,8 +609,11 @@ void NativeRender() { glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); screenManager->render(); - if (screenManager->getUIContext()->Text()) + if (screenManager->getUIContext()->Text()) { screenManager->getUIContext()->Text()->OncePerFrame(); + } + + DrawDownloadsOverlay(*screenManager->getUIContext()); if (g_TakeScreenshot) { TakeScreenshot(); @@ -618,6 +629,7 @@ void NativeUpdate(InputState &input) { } } + g_DownloadManager.Update(); screenManager->update(input); } diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 9fe23cfe59..bbefb874bb 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -46,14 +46,19 @@ restart: } void OnScreenMessages::Show(const std::string &message, float duration_s, uint32_t color, int icon, bool checkUnique) { + double now = time_now_d(); std::lock_guard guard(mutex_); if (checkUnique) { for (auto iter = messages_.begin(); iter != messages_.end(); ++iter) { - if (iter->text == message) + if (iter->text == message) { + Message msg = *iter; + msg.endTime = now + duration_s; + messages_.erase(iter); + messages_.insert(messages_.begin(), msg); return; + } } } - double now = time_now_d(); Message msg; msg.text = message; msg.color = color; diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h index de12ee3540..1cb76763e4 100644 --- a/UI/OnScreenDisplay.h +++ b/UI/OnScreenDisplay.h @@ -10,7 +10,7 @@ class DrawBuffer; class OnScreenMessages { public: - void Show(const std::string &message, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1, bool checkUnique = false); + void Show(const std::string &message, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1, bool checkUnique = true); void ShowOnOff(const std::string &message, bool b, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1); void Draw(DrawBuffer &draw); bool IsEmpty() const { return messages_.empty(); } diff --git a/UI/Store.cpp b/UI/Store.cpp new file mode 100644 index 0000000000..e6a26b7adc --- /dev/null +++ b/UI/Store.cpp @@ -0,0 +1,279 @@ +#include "native/ext/vjson/json.h" + +#include "i18n/i18n.h" +#include "ui/ui_context.h" +#include "ui/viewgroup.h" +#include "gfx_es2/draw_buffer.h" + +#include "Common/Log.h" +#include "Core/Config.h" +#include "UI/Store.h" + +const std::string storeBaseUrl = "http://store.ppsspp.org/"; + +// This is the entry in a list. Does not have install buttons and so on. +class ProductItemView : public UI::Choice { +public: + ProductItemView(const StoreEntry &entry, UI::LayoutParams *layoutParams = 0) + : entry_(entry), UI::Choice(entry.name, layoutParams) {} + + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = 300; + h = 164; + } + virtual void Update(const InputState &input_state); + virtual void Draw(UIContext &dc); + + StoreEntry GetEntry() const { return entry_; } + +private: + const StoreEntry &entry_; +}; + +void ProductItemView::Draw(UIContext &dc) { + UI::Choice::Draw(dc); + // dc.DrawText(entry_.name.c_str(), bounds_.centerX(), bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); +} + +void ProductItemView::Update(const InputState &input_state) { + View::Update(input_state); +} + +// This is a "details" view of a game. Let's you install it. +class ProductView : public UI::LinearLayout { +public: + ProductView(const StoreEntry &entry) : LinearLayout(UI::ORIENT_VERTICAL), entry_(entry), installButton_(0) { + CreateViews(); + } + + virtual void Update(const InputState &input_state); + +private: + void CreateViews(); + UI::EventReturn OnInstall(UI::EventParams &e); + UI::EventReturn OnUninstall(UI::EventParams &e); + + StoreEntry entry_; + UI::Button *installButton_; +}; + +void ProductView::CreateViews() { + using namespace UI; + Clear(); + + Add(new TextView(entry_.name)); + Add(new TextView(entry_.author)); + + I18NCategory *st = GetI18NCategory("Store"); + if (!g_GameManager.IsGameInstalled(entry_.file)) { + installButton_ = Add(new Button(st->T("Install"))); + installButton_->OnClick.Handle(this, &ProductView::OnInstall); + } else { + Add(new TextView(st->T("Already Installed"))); + Add(new Button(st->T("Uninstall")))->OnClick.Handle(this, &ProductView::OnUninstall); + } + + // Add star rating, comments etc? + Add(new TextView(entry_.description)); + + float size = entry_.size / (1024.f * 1024.f); + char temp[256]; + sprintf(temp, "%s: %.2f %s", st->T("Size"), size, st->T("MB")); + + Add(new TextView(temp)); +} + +void ProductView::Update(const InputState &input_state) { + View::Update(input_state); +} + +UI::EventReturn ProductView::OnInstall(UI::EventParams &e) { + std::string zipUrl; + if (entry_.downloadURL.empty()) { + // Construct the URL, easy to predict from our server + zipUrl = storeBaseUrl + "files/" + entry_.file + ".zip"; + } else { + // Use the provided URL, for external hosting. + zipUrl = entry_.downloadURL; + } + if (installButton_) { + installButton_->SetEnabled(false); + } + INFO_LOG(HLE, "Triggering install of %s", zipUrl.c_str()); + g_GameManager.DownloadAndInstall(zipUrl); + return UI::EVENT_DONE; +} + +UI::EventReturn ProductView::OnUninstall(UI::EventParams &e) { + g_GameManager.Uninstall(entry_.file); + CreateViews(); + return UI::EVENT_DONE; +} + + +StoreScreen::StoreScreen() : loading_(true), connectionError_(false) { + StoreFilter noFilter; + SetFilter(noFilter); + lang_ = g_Config.sLanguageIni; + loading_ = true; + + std::string indexPath = storeBaseUrl + "index.json"; + + listing_ = g_DownloadManager.StartDownload(indexPath, ""); +} + +StoreScreen::~StoreScreen() { + g_DownloadManager.CancelAll(); +} + +// Handle async download tasks +void StoreScreen::update(InputState &input) { + UIDialogScreenWithBackground::update(input); + + g_DownloadManager.Update(); + + if (listing_.get() != 0 && listing_->Done()) { + if (listing_->ResultCode() == 200) { + std::string listingJson; + listing_->buffer().TakeAll(&listingJson); + // printf("%s\n", listingJson.c_str()); + loading_ = false; + + ParseListing(listingJson); + RecreateViews(); + } else { + // Failed to contact store. Don't do anything. + connectionError_ = true; + RecreateViews(); + } + + // Forget the listing. + listing_.reset(); + } +} + +void StoreScreen::ParseListing(std::string json) { + JsonReader reader(json.c_str(), json.size()); + if (!reader.ok()) { + ELOG("Error parsing JSON from store"); + connectionError_ = true; + RecreateViews(); + return; + } + json_value *root = reader.root(); + const json_value *entries = root->getArray("entries"); + if (entries) { + entries_.clear(); + const json_value *game = entries->first_child; + while (game) { + StoreEntry e; + e.type = ENTRY_PBPZIP; + e.name = GetTranslatedString(game, "name"); + e.description = GetTranslatedString(game, "description", ""); + e.author = game->getString("author", "?"); + e.size = game->getInt("size"); + e.downloadURL = game->getString("download-url", ""); + const char *file = game->getString("file", 0); + if (!file) + continue; + e.file = file; + entries_.push_back(e); + game = game->next_sibling; + } + } +} + +void StoreScreen::CreateViews() { + using namespace UI; + + root_ = new LinearLayout(ORIENT_VERTICAL); + + I18NCategory *di = GetI18NCategory("Dialog"); + I18NCategory *st = GetI18NCategory("Store"); + + // Top bar + LinearLayout *topBar = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); + topBar->Add(new Button(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); + topBar->Add(new TextView("PPSSPP Homebrew Store")); + UI::Drawable solid(0xFFbd9939); + topBar->SetBG(solid); + + LinearLayout *content; + if (connectionError_ || loading_) { + content = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f)); + content->Add(new TextView(loading_ ? st->T("Loading...") : st->T("Connection Error"))); + content->Add(new Button(di->T("Retry")))->OnClick.Handle(this, &StoreScreen::OnRetry); + content->Add(new Button(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); + } else { + content = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f)); + ScrollView *leftScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, FILL_PARENT, 0.4f)); + content->Add(leftScroll); + LinearLayout *scrollItemView = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + leftScroll->Add(scrollItemView); + + std::vector entries = FilterEntries(); + for (size_t i = 0; i < entries.size(); i++) { + scrollItemView->Add(new ProductItemView(entries_[i]))->OnClick.Handle(this, &StoreScreen::OnGameSelected); + } + + // TODO: Similar apps, etc etc + productPanel_ = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(0.5f)); + content->Add(productPanel_); + } + root_->Add(content); +} + +std::vector StoreScreen::FilterEntries() { + std::vector filtered; + for (size_t i = 0; i < entries_.size(); i++) { + // TODO: Actually filter by category etc. + filtered.push_back(entries_[i]); + } + return filtered; +} + +UI::EventReturn StoreScreen::OnGameSelected(UI::EventParams &e) { + ProductItemView *item = static_cast(e.v); + if (!item) + return UI::EVENT_DONE; + + productPanel_->Clear(); + productPanel_->Add(new ProductView(item->GetEntry())); + return UI::EVENT_DONE; +} + +void StoreScreen::SetFilter(const StoreFilter &filter) { + filter_ = filter; + RecreateViews(); +} + +UI::EventReturn StoreScreen::OnRetry(UI::EventParams &e) { + SetFilter(filter_); + return UI::EVENT_DONE; +} + +std::string StoreScreen::GetStoreJsonURL(std::string storePath) const { + std::string path = storeBaseUrl + storePath; + if (*path.rbegin() != '/') + path += '/'; + path += "index.json"; + return path; +} + +std::string StoreScreen::GetTranslatedString(const json_value *json, std::string key, const char *fallback) const { + const json_value *dict = json->getDict("en_US"); + if (dict && json->hasChild(lang_.c_str(), JSON_OBJECT)) { + if (json->getDict(lang_.c_str())->hasChild(key.c_str(), JSON_STRING)) { + dict = json->getDict(lang_.c_str()); + } + } + const char *str = 0; + if (dict) { + str = dict->getString(key.c_str()); + } + if (str) { + return std::string(str); + } else { + return fallback ? fallback : "(error)"; + } +} diff --git a/UI/Store.h b/UI/Store.h new file mode 100644 index 0000000000..7ffa1f17e4 --- /dev/null +++ b/UI/Store.h @@ -0,0 +1,102 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "base/functional.h" +#include "ui/ui_screen.h" +#include "ui/viewgroup.h" +#include "net/http_client.h" + +#include "Core/Util/GameManager.h" +#include "UI/MiscScreens.h" + +// Game screen: Allows you to start a game, delete saves, delete the game, +// set game specific settings, etc. +// Uses GameInfoCache heavily to implement the functionality. + +struct json_value; + +enum EntryType { + ENTRY_PBPZIP, + ENTRY_ISO, +}; + +struct StoreCategory { + std::string name; +}; + +struct StoreEntry { + EntryType type; + std::string name; + std::string description; + std::string author; + std::string iconURL; + std::string file; // This is the folder name of the installed one too, and hence a "unique-ish" identifier. + std::string category; + std::string downloadURL; // Only set for games that are not hosted on store.ppsspp.org + u64 size; +}; + +struct StoreFilter { + std::string categoryId; +}; + +class StoreScreen : public UIDialogScreenWithBackground { +public: + StoreScreen(); + ~StoreScreen(); + + virtual void update(InputState &input); + virtual std::string tag() const { return "store"; } + +protected: + virtual void CreateViews(); + UI::EventReturn OnGameSelected(UI::EventParams &e); + UI::EventReturn OnCategorySelected(UI::EventParams &e); + UI::EventReturn OnRetry(UI::EventParams &e); + +private: + void SetFilter(const StoreFilter &filter); + void ParseListing(std::string json); + std::vector FilterEntries(); + + std::string GetStoreJsonURL(std::string storePath) const; + std::string GetTranslatedString(const json_value *json, std::string key, const char *fallback = 0) const; + + std::shared_ptr listing_; + std::shared_ptr image_; + + // TODO: Replace with a PathBrowser or similar. Though that one only supports + // local filesystems at the moment. + std::string storePath_; + + bool loading_; + bool connectionError_; + + std::map categories_; + + // We download the whole store in one JSON request. Not super scalable but works fine + // for now. entries_ contains all the products in the store. + std::vector entries_; + + StoreFilter filter_; + std::string lang_; + + UI::ViewGroup *productPanel_; +}; + diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index b12a3b3972..e08f3267ca 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -28,47 +28,59 @@ #include "GamepadEmu.h" #include "i18n/i18n.h" -static const int leftMargin = 140; +static const int leftColumnWidth = 140; -// convert from screen coordinates (leftMargin to dp_xres) to actual fullscreen coordinates (0 to 1.0) -static inline float toFullscreenCoord(int screenx) { - return (float)(screenx - leftMargin) / (dp_xres - leftMargin); +static u32 GetButtonColor() { + return g_Config.iTouchButtonStyle == 1 ? 0xFFFFFF : 0xc0b080; } -// convert from external fullscreen coordinates(0 to 1.0) to the current partial coordinates (leftMargin to dp_xres) +// convert from screen coordinates (leftColumnWidth to dp_xres) to actual fullscreen coordinates (0 to 1.0) +static inline float toFullscreenCoord(int screenx) { + return (float)(screenx - leftColumnWidth) / (dp_xres - leftColumnWidth); +} + +// convert from external fullscreen coordinates(0 to 1.0) to the current partial coordinates (leftColumnWidth to dp_xres) static inline int fromFullscreenCoord(float controllerX) { - return leftMargin + (dp_xres - leftMargin) * controllerX; + return leftColumnWidth + (dp_xres - leftColumnWidth) * controllerX; }; class DragDropButton : public MultiTouchButton { public: - DragDropButton(float &x, float &y, int bgImg, int img, float scale) + DragDropButton(float &x, float &y, int bgImg, int img, float &scale) : MultiTouchButton(bgImg, img, scale, new UI::AnchorLayoutParams(fromFullscreenCoord(x), y*dp_yres, UI::NONE, UI::NONE, true)), - x_(x), y_(y) { - scale_ = scale; + x_(x), y_(y), theScale_(scale) { + scale_ = theScale_; } virtual bool IsDown() { - //don't want the button to enlarge and throw the user's perspective - //of button size off whack. + // Don't want the button to enlarge and throw the user's perspective + // of button size off whack. return false; }; - void SavePosition() { + virtual void SavePosition() { x_ = toFullscreenCoord(bounds_.centerX()); y_ = bounds_.centerY() / dp_yres; + scale_ = theScale_; } + virtual float GetScale() const { return theScale_; } + virtual void SetScale(float s) { theScale_ = s; scale_ = s; } + + virtual float GetSpacing() const { return 1.0f; } + virtual void SetSpacing(float s) { } + private: float &x_, &y_; + float &theScale_; }; class PSPActionButtons : public DragDropButton { public: - PSPActionButtons(float &x, float &y, int actionButtonSpacing, float scale) - : DragDropButton(x, y, -1, -1, scale), actionButtonSpacing_(actionButtonSpacing) { + PSPActionButtons(float &x, float &y, float &scale, float &spacing) + : DragDropButton(x, y, -1, -1, scale), spacing_(spacing) { using namespace UI; - roundId_ = I_ROUND; + roundId_ = g_Config.iTouchButtonStyle ? I_ROUND_LINE : I_ROUND; circleId_ = I_CIRCLE; crossId_ = I_CROSS; @@ -97,89 +109,101 @@ public: void Draw(UIContext &dc) { float opacity = g_Config.iTouchButtonOpacity / 100.0f; - uint32_t colorBg = colorAlpha(0xc0b080, opacity); + uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); uint32_t color = colorAlpha(0xFFFFFF, opacity); int centerX = bounds_.centerX(); int centerY = bounds_.centerY(); + float spacing = spacing_ * baseActionButtonSpacing; if (circleVisible_) { - dc.Draw()->DrawImageRotated(roundId_, centerX + actionButtonSpacing_, centerY, scale_, 0, colorBg, false); - dc.Draw()->DrawImageRotated(circleId_, centerX + actionButtonSpacing_, centerY, scale_, 0, color, false); + dc.Draw()->DrawImageRotated(roundId_, centerX + spacing, centerY, scale_, 0, colorBg, false); + dc.Draw()->DrawImageRotated(circleId_, centerX + spacing, centerY, scale_, 0, color, false); } if (crossVisible_) { - dc.Draw()->DrawImageRotated(roundId_, centerX, centerY + actionButtonSpacing_, scale_, 0, colorBg, false); - dc.Draw()->DrawImageRotated(crossId_, centerX, centerY + actionButtonSpacing_, scale_, 0, color, false); + dc.Draw()->DrawImageRotated(roundId_, centerX, centerY + spacing, scale_, 0, colorBg, false); + dc.Draw()->DrawImageRotated(crossId_, centerX, centerY + spacing, scale_, 0, color, false); } if (triangleVisible_) { - dc.Draw()->DrawImageRotated(roundId_, centerX, centerY - actionButtonSpacing_, scale_, 0, colorBg, false); - dc.Draw()->DrawImageRotated(triangleId_, centerX, centerY - actionButtonSpacing_, scale_, 0, color, false); + float y = centerY - spacing; + y -= 2.8f * scale_; + dc.Draw()->DrawImageRotated(roundId_, centerX, centerY - spacing, scale_, 0, colorBg, false); + dc.Draw()->DrawImageRotated(triangleId_, centerX, y, scale_, 0, color, false); } - - if (squareVisible_){ - dc.Draw()->DrawImageRotated(roundId_, centerX - actionButtonSpacing_, centerY, scale_, 0, colorBg, false); - dc.Draw()->DrawImageRotated(squareId_, centerX - actionButtonSpacing_, centerY, scale_, 0, color, false); + + if (squareVisible_) { + dc.Draw()->DrawImageRotated(roundId_, centerX - spacing, centerY, scale_, 0, colorBg, false); + dc.Draw()->DrawImageRotated(squareId_, centerX - spacing, centerY, scale_, 0, color, false); } }; void GetContentDimensions(const UIContext &dc, float &w, float &h) const{ const AtlasImage &image = dc.Draw()->GetAtlas()->images[roundId_]; - w = 2 * actionButtonSpacing_ + image.w * scale_; - h = 2 * actionButtonSpacing_ + image.h * scale_; - //w += 2 * actionButtonSpacing_; - //h += 2 * actionButtonSpacing_; - }; + w = (2 * baseActionButtonSpacing * spacing_) + image.w * scale_; + h = (2 * baseActionButtonSpacing * spacing_) + image.h * scale_; + } + + virtual float GetSpacing() const { return spacing_; } + virtual void SetSpacing(float s) { spacing_ = s; } + + virtual void SavePosition() { + DragDropButton::SavePosition(); + } private: - bool circleVisible_, crossVisible_, triangleVisible_, squareVisible_; int roundId_; int circleId_, crossId_, triangleId_, squareId_; - int actionButtonSpacing_; + float &spacing_; }; class PSPDPadButtons : public DragDropButton { public: - PSPDPadButtons(float &x, float &y, int DpadRadius, float scale) - : DragDropButton(x, y, -1, -1, scale), DpadRadius_(DpadRadius) { + PSPDPadButtons(float &x, float &y, float &scale, float &spacing) + : DragDropButton(x, y, -1, -1, scale), spacing_(spacing) { } void Draw(UIContext &dc) { float opacity = g_Config.iTouchButtonOpacity / 100.0f; - uint32_t colorBg = colorAlpha(0xc0b080, opacity); + uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); uint32_t color = colorAlpha(0xFFFFFF, opacity); static const float xoff[4] = {1, 0, -1, 0}; static const float yoff[4] = {0, 1, 0, -1}; + int dirImage = g_Config.iTouchButtonStyle ? I_DIR_LINE : I_DIR; + for (int i = 0; i < 4; i++) { - float x = bounds_.centerX() + xoff[i] * DpadRadius_; - float y = bounds_.centerY() + yoff[i] * DpadRadius_; + float r = D_pad_Radius * spacing_; + float x = bounds_.centerX() + xoff[i] * r; + float y = bounds_.centerY() + yoff[i] * r; + float x2 = bounds_.centerX() + xoff[i] * (r + 10.f * scale_); + float y2 = bounds_.centerY() + yoff[i] * (r + 10.f * scale_); float angle = i * M_PI / 2; - dc.Draw()->DrawImageRotated(I_DIR, x, y, scale_, angle + PI, colorBg, false); - dc.Draw()->DrawImageRotated(I_ARROW, x, y, scale_, angle + PI, color); + dc.Draw()->DrawImageRotated(dirImage, x, y, scale_, angle + PI, colorBg, false); + dc.Draw()->DrawImageRotated(I_ARROW, x2, y2, scale_, angle + PI, color); } } void GetContentDimensions(const UIContext &dc, float &w, float &h) const{ const AtlasImage &image = dc.Draw()->GetAtlas()->images[I_DIR]; - w = 2 * DpadRadius_ + image.w * scale_; - h = 2 * DpadRadius_ + image.h * scale_; - - //w += 2 * DpadRadius_; - //h += 2 * DpadRadius_; + w = 2 * D_pad_Radius * spacing_ + image.w * scale_; + h = 2 * D_pad_Radius * spacing_ + image.h * scale_; }; + float GetSpacing() const { return spacing_; } + virtual void SetSpacing(float s) { spacing_ = s; } + private: - int DpadRadius_; -}; + float &spacing_; +}; TouchControlLayoutScreen::TouchControlLayoutScreen() { pickedControl_ = 0; @@ -190,37 +214,58 @@ void TouchControlLayoutScreen::touch(const TouchInput &touch) { using namespace UI; + int mode = mode_->GetSelection(); + if ((touch.flags & TOUCH_MOVE) && pickedControl_ != 0) { - const Bounds &bounds = pickedControl_->GetBounds(); - - int mintouchX = leftMargin + bounds.w * 0.5; - int maxTouchX = dp_xres - bounds.w * 0.5; + if (mode == 0) { + const Bounds &bounds = pickedControl_->GetBounds(); - int minTouchY = bounds.h * 0.5; - int maxTouchY = dp_yres - bounds.h * 0.5; + int mintouchX = leftColumnWidth + bounds.w * 0.5; + int maxTouchX = dp_xres - bounds.w * 0.5; - int newX = bounds.centerX(), newY = bounds.centerY(); + int minTouchY = bounds.h * 0.5; + int maxTouchY = dp_yres - bounds.h * 0.5; - //we have to handle x and y separately since even if x is blocked, y may not be. - if (touch.x > mintouchX && touch.x < maxTouchX) { - //if the leftmost point of the control is ahead of the margin, - //move it. Otherwise, don't. - newX = touch.x; + int newX = bounds.centerX(), newY = bounds.centerY(); + + // we have to handle x and y separately since even if x is blocked, y may not be. + if (touch.x > mintouchX && touch.x < maxTouchX) { + // if the leftmost point of the control is ahead of the margin, + // move it. Otherwise, don't. + newX = touch.x; + } + if (touch.y > minTouchY && touch.y < maxTouchY) { + newY = touch.y; + } + pickedControl_->ReplaceLayoutParams(new UI::AnchorLayoutParams(newX, newY, NONE, NONE, true)); + } else if (mode == 1) { + // Resize. Vertical = scaling, horizontal = spacing; + // Up should be bigger so let's negate in that direction + float diffX = (touch.x - startX_); + float diffY = -(touch.y - startY_); + + float movementScale = 0.02f; + float newScale = startScale_ + diffY * movementScale; + float newSpacing = startSpacing_ + diffX * movementScale; + if (newScale > 3.0f) newScale = 3.0f; + if (newScale < 0.5f) newScale = 0.5f; + if (newSpacing > 3.0f) newSpacing = 3.0f; + if (newSpacing < 0.5f) newSpacing = 0.5f; + pickedControl_->SetSpacing(newSpacing); + pickedControl_->SetScale(newScale); } - if (touch.y > minTouchY && touch.y < maxTouchY) { - newY = touch.y; - } - - // ILOG("position: x = %d; y = %d", newX, newY); - pickedControl_->ReplaceLayoutParams(new UI::AnchorLayoutParams(newX, newY, NONE, NONE, true)); } if ((touch.flags & TOUCH_DOWN) && pickedControl_ == 0) { - ILOG("->->->picked up") pickedControl_ = getPickedControl(touch.x, touch.y); + if (pickedControl_) { + startX_ = touch.x; + startY_ = touch.y; + startSpacing_ = pickedControl_->GetSpacing(); + startScale_ = pickedControl_->GetScale(); + } } if ((touch.flags & TOUCH_UP) && pickedControl_ != 0) { pickedControl_->SavePosition(); - ILOG("->->->dropped down") pickedControl_ = 0; } }; @@ -235,24 +280,9 @@ UI::EventReturn TouchControlLayoutScreen::OnVisibility(UI::EventParams &e) { } UI::EventReturn TouchControlLayoutScreen::OnReset(UI::EventParams &e) { - g_Config.iActionButtonSpacing = -1; - g_Config.fActionButtonCenterX = -1.0; - g_Config.fActionButtonCenterY = -1.0; - g_Config.iDpadRadius = -1; - g_Config.fDpadX = -1.0; - g_Config.fDpadY = -1.0; - g_Config.fStartKeyX = -1.0; - g_Config.fStartKeyY = -1.0; - g_Config.fSelectKeyX = -1.0; - g_Config.fSelectKeyY = -1.0; - g_Config.fUnthrottleKeyX = -1.0; - g_Config.fUnthrottleKeyY = -1.0; - g_Config.fLKeyX = -1.0; - g_Config.fLKeyY = -1.0; - g_Config.fRKeyX = -1.0; - g_Config.fRKeyY = -1.0; - g_Config.fAnalogStickX = -1.0; - g_Config.fAnalogStickY = -1.0; + ILOG("Resetting touch control layout"); + float defaultScale = 1.15; + g_Config.ResetControlLayout(); InitPadLayout(); RecreateViews(); return UI::EVENT_DONE; @@ -273,17 +303,26 @@ void TouchControlLayoutScreen::CreateViews() { root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - Choice *reset = new Choice(d->T("Reset"), "", false, new AnchorLayoutParams(leftMargin, WRAP_CONTENT, 10, NONE, NONE, 84)); - Choice *back = new Choice(d->T("Back"), "", false, new AnchorLayoutParams(leftMargin, WRAP_CONTENT, 10, NONE, NONE, 10)); - Choice *visibility = new Choice(c->T("Visibility"), "", false, new AnchorLayoutParams(leftMargin, WRAP_CONTENT, 10, NONE, NONE, 158)); + Choice *reset = new Choice(d->T("Reset"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 84)); + Choice *back = new Choice(d->T("Back"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 10)); + Choice *visibility = new Choice(c->T("Visibility"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 158)); + // controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fButtonScale, 0.80, 2.0, c->T("Button Scaling"), screenManager())) + // ->OnChange.Handle(this, &GameSettingsScreen::OnChangeControlScaling); + + mode_ = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 158 + 64 + 10)); + mode_->AddChoice(d->T("Move")); + mode_->AddChoice(d->T("Resize")); + mode_->SetSelection(0); + reset->OnClick.Handle(this, &TouchControlLayoutScreen::OnReset); back->OnClick.Handle(this, &UIScreen::OnBack); visibility->OnClick.Handle(this, &TouchControlLayoutScreen::OnVisibility); + root_->Add(mode_); root_->Add(visibility); root_->Add(reset); root_->Add(back); - TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftMargin, new AnchorLayoutParams(10, 0, 10, 0, false)); + TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, new AnchorLayoutParams(10, 0, 10, 0, false)); root_->Add(tabHolder); // this is more for show than anything else. It's used to provide a boundary @@ -295,14 +334,14 @@ void TouchControlLayoutScreen::CreateViews() { tabHolder->AddTab(ms->T("Controls"), controlsHolder); - if (!g_Config.bShowTouchControls){ + if (!g_Config.bShowTouchControls) { + // Shouldn't even be able to get here as the way into this dialog should be closed. return; } - float scale = g_Config.fButtonScale; controls_.clear(); - PSPActionButtons *actionButtons = new PSPActionButtons(g_Config.fActionButtonCenterX, g_Config.fActionButtonCenterY, g_Config.iActionButtonSpacing, scale); + PSPActionButtons *actionButtons = new PSPActionButtons(g_Config.fActionButtonCenterX, g_Config.fActionButtonCenterY, g_Config.fActionButtonScale, g_Config.fActionButtonSpacing); actionButtons->setCircleVisibility(g_Config.bShowTouchCircle); actionButtons->setCrossVisibility(g_Config.bShowTouchCross); actionButtons->setTriangleVisibility(g_Config.bShowTouchTriangle); @@ -310,36 +349,42 @@ void TouchControlLayoutScreen::CreateViews() { controls_.push_back(actionButtons); + int rectImage = g_Config.iTouchButtonStyle ? I_RECT_LINE : I_RECT; + int shoulderImage = g_Config.iTouchButtonStyle ? I_SHOULDER_LINE : I_SHOULDER; + int dirImage = g_Config.iTouchButtonStyle ? I_DIR_LINE : I_DIR; + int stickImage = g_Config.iTouchButtonStyle ? I_STICK_LINE : I_STICK; + int stickBg = g_Config.iTouchButtonStyle ? I_STICK_BG_LINE : I_STICK_BG; + if (g_Config.bShowTouchDpad) { - controls_.push_back(new PSPDPadButtons(g_Config.fDpadX, g_Config.fDpadY, g_Config.iDpadRadius, scale)); + controls_.push_back(new PSPDPadButtons(g_Config.fDpadX, g_Config.fDpadY, g_Config.fDpadScale, g_Config.fDpadSpacing)); } if (g_Config.bShowTouchSelect) { - controls_.push_back(new DragDropButton(g_Config.fSelectKeyX, g_Config.fSelectKeyY, I_RECT, I_SELECT, scale)); + controls_.push_back(new DragDropButton(g_Config.fSelectKeyX, g_Config.fSelectKeyY, rectImage, I_SELECT, g_Config.fSelectKeyScale)); } if (g_Config.bShowTouchStart) { - controls_.push_back(new DragDropButton(g_Config.fStartKeyX, g_Config.fStartKeyY, I_RECT, I_START, scale)); + controls_.push_back(new DragDropButton(g_Config.fStartKeyX, g_Config.fStartKeyY, rectImage, I_START, g_Config.fStartKeyScale)); } if (g_Config.bShowTouchUnthrottle) { - DragDropButton *unthrottle = new DragDropButton(g_Config.fUnthrottleKeyX, g_Config.fUnthrottleKeyY, I_RECT, I_ARROW, scale); + DragDropButton *unthrottle = new DragDropButton(g_Config.fUnthrottleKeyX, g_Config.fUnthrottleKeyY, rectImage, I_ARROW, g_Config.fUnthrottleKeyScale); unthrottle->SetAngle(180.0f); controls_.push_back(unthrottle); } if (g_Config.bShowTouchLTrigger) { - controls_.push_back(new DragDropButton(g_Config.fLKeyX, g_Config.fLKeyY, I_SHOULDER, I_L, scale)); + controls_.push_back(new DragDropButton(g_Config.fLKeyX, g_Config.fLKeyY, shoulderImage, I_L, g_Config.fLKeyScale)); } if (g_Config.bShowTouchRTrigger) { - DragDropButton *rbutton = new DragDropButton(g_Config.fRKeyX, g_Config.fRKeyY, I_SHOULDER, I_R, scale); + DragDropButton *rbutton = new DragDropButton(g_Config.fRKeyX, g_Config.fRKeyY, shoulderImage, I_R, g_Config.fRKeyScale); rbutton->FlipImageH(true); controls_.push_back(rbutton); } if (g_Config.bShowTouchAnalogStick) { - controls_.push_back(new DragDropButton(g_Config.fAnalogStickX, g_Config.fAnalogStickY, I_STICKBG, I_STICK, scale)); + controls_.push_back(new DragDropButton(g_Config.fAnalogStickX, g_Config.fAnalogStickY, stickBg, stickImage, g_Config.fAnalogStickScale)); }; for (size_t i = 0; i < controls_.size(); i++) { diff --git a/UI/TouchControlLayoutScreen.h b/UI/TouchControlLayoutScreen.h index 728361b5cc..d62ee916e5 100644 --- a/UI/TouchControlLayoutScreen.h +++ b/UI/TouchControlLayoutScreen.h @@ -19,6 +19,7 @@ #include "base/functional.h" #include "ui/view.h" +#include "ui/viewgroup.h" #include "MiscScreens.h" #include @@ -40,5 +41,12 @@ protected: private: DragDropButton *pickedControl_; std::vector controls_; + UI::ChoiceStrip *mode_; DragDropButton *getPickedControl(const int x, const int y); + + // Touch down state for drag to resize etc + float startX_; + float startY_; + float startScale_; + float startSpacing_; }; diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index 273c74c81d..1333c3665a 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -31,9 +31,11 @@ + +
@@ -49,9 +51,11 @@ + + @@ -111,7 +115,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib + ../common;..;../native;../native/ext/glew;../ext/zlib;../native/ext true false false @@ -128,7 +132,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib + ../common;..;../native;../native/ext/glew;../ext/zlib;../native/ext true false false @@ -147,7 +151,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib + ../common;..;../native;../native/ext/glew;../ext/zlib;../native/ext false Speed true @@ -169,7 +173,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib + ../common;..;../native;../native/ext/glew;../ext/zlib;../native/ext false true false @@ -184,4 +188,4 @@ - \ No newline at end of file + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 31b7e04bce..818693e77a 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -40,6 +40,10 @@ Screens + + Screens + + @@ -80,10 +84,14 @@ Screens + + Screens + + {faee5dce-633b-4ba6-b19d-ea70ee3c1c38} - \ No newline at end of file + diff --git a/UI/ui_atlas.cpp b/UI/ui_atlas.cpp index bb7744be55..0a57af94ff 100644 --- a/UI/ui_atlas.cpp +++ b/UI/ui_atlas.cpp @@ -3,1171 +3,1472 @@ #include "ui_atlas.h" const AtlasChar font_UBUNTU24_chardata[] = { -// RANGE: 0x20 - 0x80, start 0x18 +// RANGE: 0x20 - 0x80, start 0x21 {0.000000f, 0.000000f, 0.000488f, 0.000488f, -2.0000f, -4.0000f, 7.5000f, 1, 1}, // 0020 - {0.743652f, 0.082520f, 0.747559f, 0.096680f, 0.2500f, -28.1875f, 7.8750f, 8, 29}, // 0021 - {0.296387f, 0.304688f, 0.302246f, 0.311035f, 0.1875f, -28.1875f, 11.6875f, 12, 13}, // 0022 - {0.228516f, 0.777832f, 0.238281f, 0.791992f, -1.0625f, -28.1875f, 18.0000f, 20, 29}, // 0023 - {0.865234f, 0.758301f, 0.874023f, 0.775879f, -0.2500f, -32.0000f, 17.3125f, 18, 36}, // 0024 - {0.286621f, 0.067871f, 0.298340f, 0.082031f, -0.3750f, -28.5000f, 22.6875f, 24, 29}, // 0025 - {0.298828f, 0.035645f, 0.309570f, 0.049805f, -0.8750f, -28.5000f, 19.7500f, 22, 29}, // 0026 - {0.330566f, 0.114258f, 0.334473f, 0.120605f, -0.1875f, -28.1875f, 6.8125f, 8, 13}, // 0027 - {0.538086f, 0.813965f, 0.543945f, 0.833008f, -0.0625f, -31.0000f, 10.0625f, 12, 39}, // 0028 - {0.204102f, 0.815918f, 0.209961f, 0.834961f, -1.6250f, -31.0000f, 10.1250f, 12, 39}, // 0029 - {0.319336f, 0.316895f, 0.326660f, 0.324707f, -0.8750f, -21.9375f, 13.1875f, 15, 16}, // 002a - {0.270020f, 0.695313f, 0.279297f, 0.706055f, -0.8750f, -24.0625f, 17.2500f, 19, 22}, // 002b - {0.395996f, 0.257813f, 0.400391f, 0.264160f, -1.0625f, -7.5625f, 6.8750f, 9, 13}, // 002c - {0.088867f, 0.346680f, 0.095215f, 0.350098f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 002d - {0.331055f, 0.346191f, 0.334961f, 0.350098f, 0.3125f, -7.3750f, 8.3125f, 8, 8}, // 002e - {0.954590f, 0.632813f, 0.962402f, 0.647949f, -1.8750f, -28.2500f, 12.1250f, 16, 31}, // 002f - {0.659668f, 0.177734f, 0.668945f, 0.191895f, -0.3125f, -28.5000f, 17.5625f, 19, 29}, // 0030 - {0.430176f, 0.833496f, 0.436523f, 0.847656f, 1.0625f, -28.5625f, 17.5625f, 13, 29}, // 0031 - {0.733398f, 0.787109f, 0.742676f, 0.801270f, -0.2500f, -28.5000f, 17.5000f, 19, 29}, // 0032 - {0.592285f, 0.788086f, 0.601563f, 0.802246f, -0.3750f, -28.5000f, 17.5000f, 19, 29}, // 0033 - {0.238770f, 0.777832f, 0.248535f, 0.791992f, -0.8750f, -28.1875f, 17.5625f, 20, 29}, // 0034 - {0.091309f, 0.799805f, 0.100098f, 0.813965f, 0.1250f, -28.1875f, 17.5000f, 18, 29}, // 0035 - {0.479492f, 0.789063f, 0.488770f, 0.803223f, -0.0625f, -28.5000f, 17.5625f, 19, 29}, // 0036 - {0.489258f, 0.789063f, 0.498535f, 0.803223f, -0.6250f, -28.1875f, 17.5625f, 19, 29}, // 0037 - {0.055176f, 0.789551f, 0.064453f, 0.803711f, -0.5000f, -28.5000f, 17.5625f, 19, 29}, // 0038 - {0.064941f, 0.789551f, 0.074219f, 0.803711f, -0.5625f, -28.5000f, 17.5000f, 19, 29}, // 0039 - {0.555664f, 0.381836f, 0.559570f, 0.392578f, 0.3125f, -21.9375f, 7.9375f, 8, 22}, // 003a - {0.655273f, 0.193848f, 0.659668f, 0.207031f, -0.1875f, -21.9375f, 7.8750f, 9, 27}, // 003b - {0.174316f, 0.842773f, 0.182129f, 0.852539f, -1.0000f, -20.6875f, 15.1250f, 16, 20}, // 003c - {0.077148f, 0.646973f, 0.085449f, 0.653809f, 0.1875f, -20.1250f, 16.9375f, 17, 14}, // 003d - {0.913574f, 0.681641f, 0.921875f, 0.691406f, -0.1250f, -20.5000f, 15.3750f, 17, 20}, // 003e - {0.991211f, 0.811523f, 0.999512f, 0.825684f, -1.2500f, -28.5625f, 14.3750f, 17, 29}, // 003f - {0.126953f, 0.028809f, 0.141113f, 0.046387f, -0.5000f, -27.6250f, 27.5625f, 29, 36}, // 0040 - {0.701660f, 0.163086f, 0.712402f, 0.177246f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0041 - {0.366699f, 0.777832f, 0.376465f, 0.791992f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0042 - {0.874512f, 0.777832f, 0.884277f, 0.791992f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0043 - {0.009766f, 0.778320f, 0.019531f, 0.792480f, 0.3125f, -28.1875f, 19.8125f, 20, 29}, // 0044 - {0.191406f, 0.799805f, 0.200195f, 0.813965f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0045 - {0.400391f, 0.799805f, 0.409180f, 0.813965f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0046 - {0.885742f, 0.768066f, 0.895996f, 0.782227f, -0.3125f, -28.5000f, 19.8750f, 21, 29}, // 0047 - {0.163086f, 0.768555f, 0.173340f, 0.782715f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 0048 - {0.174316f, 0.208496f, 0.178223f, 0.222656f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0049 - {0.751953f, 0.799805f, 0.760742f, 0.813965f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 004a - {0.539551f, 0.769043f, 0.549805f, 0.783203f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 004b - {0.644531f, 0.800293f, 0.653320f, 0.814453f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 004c - {0.273926f, 0.100098f, 0.286133f, 0.114258f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 004d - {0.896484f, 0.769043f, 0.906738f, 0.783203f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 004e - {0.140137f, 0.769531f, 0.150391f, 0.783691f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 004f - {0.412598f, 0.778320f, 0.422363f, 0.792480f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0050 - {0.206055f, 0.047852f, 0.217285f, 0.063477f, -0.3750f, -28.5625f, 20.6250f, 23, 32}, // 0051 - {0.439941f, 0.778320f, 0.449707f, 0.792480f, 0.3125f, -28.1875f, 18.9375f, 20, 29}, // 0052 - {0.772949f, 0.778320f, 0.782715f, 0.792480f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0053 - {0.091309f, 0.770020f, 0.101563f, 0.784180f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0054 - {0.192871f, 0.770020f, 0.203125f, 0.784180f, 0.0625f, -28.1875f, 20.1250f, 21, 29}, // 0055 - {0.897461f, 0.754395f, 0.908691f, 0.768555f, -1.6875f, -28.1875f, 18.6875f, 23, 29}, // 0056 - {0.736328f, 0.660156f, 0.750488f, 0.674316f, -1.5000f, -28.1875f, 25.8125f, 29, 29}, // 0057 - {0.205078f, 0.761230f, 0.215820f, 0.775391f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0058 - {0.486816f, 0.761230f, 0.497559f, 0.775391f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 0059 - {0.794434f, 0.789551f, 0.803711f, 0.803711f, -0.6875f, -28.1875f, 16.6875f, 19, 29}, // 005a - {0.994629f, 0.780273f, 0.999512f, 0.798828f, 0.1250f, -31.8125f, 8.4375f, 10, 38}, // 005b - {0.831543f, 0.806641f, 0.839355f, 0.821777f, -1.6250f, -28.2500f, 12.3750f, 16, 31}, // 005c - {0.414551f, 0.833496f, 0.419434f, 0.852051f, -1.8125f, -31.8125f, 8.3750f, 10, 38}, // 005d - {0.277832f, 0.518555f, 0.285156f, 0.526855f, -1.1250f, -28.2500f, 12.7500f, 15, 17}, // 005e - {0.080078f, 0.346680f, 0.088379f, 0.350098f, -1.8750f, -4.0625f, 13.3125f, 17, 7}, // 005f - {0.781250f, 0.560059f, 0.786621f, 0.564453f, -0.8750f, -29.2500f, 9.8750f, 11, 9}, // 0060 - {0.326172f, 0.830078f, 0.334961f, 0.841309f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0061 - {0.342285f, 0.782715f, 0.351074f, 0.797852f, -0.0625f, -29.8750f, 16.7500f, 18, 31}, // 0062 - {0.509766f, 0.832520f, 0.518066f, 0.843750f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0063 - {0.082031f, 0.785156f, 0.090820f, 0.800293f, -0.6875f, -29.8750f, 16.7500f, 18, 31}, // 0064 - {0.447266f, 0.830078f, 0.456055f, 0.841309f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0065 - {0.502441f, 0.823730f, 0.509277f, 0.838867f, -1.3125f, -30.2500f, 10.0625f, 14, 31}, // 0066 - {0.581055f, 0.795898f, 0.589844f, 0.810547f, -0.6250f, -22.3125f, 16.7500f, 18, 30}, // 0067 - {0.818359f, 0.209473f, 0.826660f, 0.224121f, -0.1250f, -29.9375f, 16.6875f, 17, 30}, // 0068 - {0.598633f, 0.049316f, 0.602539f, 0.063965f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0069 - {0.141602f, 0.828125f, 0.146973f, 0.846680f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 006a - {0.783203f, 0.795898f, 0.791992f, 0.810547f, -0.0625f, -29.9375f, 15.5000f, 18, 30}, // 006b - {0.711426f, 0.064941f, 0.715332f, 0.079590f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 006c - {0.729492f, 0.720703f, 0.742188f, 0.731934f, -0.0625f, -22.3125f, 25.6875f, 26, 23}, // 006d - {0.252441f, 0.835938f, 0.260742f, 0.847168f, -0.0625f, -22.3125f, 16.8125f, 17, 23}, // 006e - {0.981934f, 0.824707f, 0.991211f, 0.835938f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 006f - {0.879883f, 0.795898f, 0.888672f, 0.810547f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0070 - {0.157715f, 0.796387f, 0.166504f, 0.811035f, -0.6875f, -22.2500f, 16.7500f, 18, 30}, // 0071 - {0.848633f, 0.694824f, 0.854980f, 0.706055f, -0.0625f, -22.3125f, 10.4375f, 13, 23}, // 0072 - {0.363770f, 0.835938f, 0.372070f, 0.847168f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0073 - {0.967773f, 0.587402f, 0.974121f, 0.600586f, -1.5000f, -26.4375f, 10.1875f, 13, 27}, // 0074 - {0.602539f, 0.835938f, 0.610840f, 0.847168f, -0.1250f, -21.9375f, 16.7500f, 17, 23}, // 0075 - {0.279785f, 0.828125f, 0.289063f, 0.838867f, -1.5000f, -22.0000f, 15.0000f, 19, 22}, // 0076 - {0.354492f, 0.123047f, 0.366699f, 0.133789f, -1.3750f, -22.0000f, 22.0625f, 25, 22}, // 0077 - {0.082520f, 0.832031f, 0.091309f, 0.842773f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0078 - {0.249023f, 0.782715f, 0.258301f, 0.797363f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0079 - {0.866211f, 0.836426f, 0.874512f, 0.847168f, -0.6875f, -22.0000f, 15.0000f, 17, 22}, // 007a - {0.993164f, 0.539551f, 0.999512f, 0.557617f, -1.1250f, -30.5625f, 10.0000f, 13, 37}, // 007b - {0.129395f, 0.750000f, 0.132813f, 0.766113f, 0.1875f, -28.1875f, 7.4375f, 7, 33}, // 007c - {0.290527f, 0.813477f, 0.296875f, 0.831543f, -1.5000f, -30.5625f, 10.0000f, 13, 37}, // 007d - {0.173828f, 0.041992f, 0.183594f, 0.047363f, -0.1875f, -17.3750f, 19.6250f, 20, 11}, // 007e - {0.395996f, 0.714355f, 0.409180f, 0.727539f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 007f -// RANGE: 0x80 - 0x81, start 0x78 - {0.409668f, 0.714355f, 0.422852f, 0.727539f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0080 -// RANGE: 0xa2 - 0x100, start 0x79 - {0.525879f, 0.796387f, 0.534668f, 0.811035f, -0.7500f, -25.9375f, 16.6875f, 18, 30}, // 00a2 - {0.710449f, 0.791016f, 0.719727f, 0.805176f, -0.7500f, -28.5000f, 17.3750f, 19, 29}, // 00a3 - {0.369629f, 0.588379f, 0.380859f, 0.601074f, -0.5625f, -25.0625f, 21.6875f, 23, 26}, // 00a4 - {0.391113f, 0.770020f, 0.401367f, 0.784180f, -1.5000f, -28.1875f, 18.0000f, 21, 29}, // 00a5 - {0.995605f, 0.630859f, 0.999512f, 0.646973f, 0.0625f, -28.1875f, 7.3750f, 8, 33}, // 00a6 - {0.989746f, 0.087891f, 0.999512f, 0.105957f, -0.5000f, -28.5000f, 18.3750f, 20, 37}, // 00a7 - {0.288574f, 0.329102f, 0.295898f, 0.333008f, 0.5000f, -28.1875f, 15.8125f, 15, 8}, // 00a8 - {0.596191f, 0.706055f, 0.608887f, 0.720215f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00a9 - {0.359375f, 0.017578f, 0.366211f, 0.026367f, -0.1875f, -28.5625f, 13.3125f, 14, 18}, // 00aa - {0.322266f, 0.114258f, 0.330078f, 0.123047f, -0.5625f, -19.1875f, 14.3750f, 16, 18}, // 00ab - {0.161133f, 0.074219f, 0.168945f, 0.079590f, -0.1250f, -17.1875f, 16.3125f, 16, 11}, // 00ac - {0.189941f, 0.585449f, 0.196289f, 0.588867f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 00ad - {0.629395f, 0.706055f, 0.642090f, 0.720215f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00ae - {0.296387f, 0.329102f, 0.303711f, 0.332520f, 0.0625f, -28.1875f, 14.7500f, 15, 7}, // 00af - {0.285645f, 0.518555f, 0.291504f, 0.524902f, 0.0625f, -28.5625f, 11.8750f, 12, 13}, // 00b0 - {0.706543f, 0.819336f, 0.715332f, 0.832031f, -0.5000f, -25.2500f, 16.6250f, 18, 26}, // 00b1 - {0.055176f, 0.779297f, 0.061523f, 0.788086f, -0.3125f, -28.5625f, 12.4375f, 13, 18}, // 00b2 - {0.770020f, 0.705078f, 0.776855f, 0.713867f, -0.4375f, -28.5625f, 12.5625f, 14, 18}, // 00b3 - {0.795898f, 0.568848f, 0.801270f, 0.573242f, -0.1250f, -29.2500f, 10.3125f, 11, 9}, // 00b4 - {0.281738f, 0.813477f, 0.290039f, 0.827637f, 0.1875f, -21.9375f, 17.5000f, 17, 29}, // 00b5 - {0.000000f, 0.822266f, 0.007813f, 0.836426f, -1.0000f, -28.1875f, 15.0625f, 16, 29}, // 00b6 - {0.903809f, 0.482910f, 0.907715f, 0.486816f, 0.4375f, -17.6250f, 8.4375f, 8, 8}, // 00b7 - {0.334473f, 0.285156f, 0.338867f, 0.291016f, -0.3125f, -4.0000f, 7.7500f, 9, 12}, // 00b8 - {0.455566f, 0.015137f, 0.459961f, 0.023926f, -0.6875f, -28.5625f, 8.2500f, 9, 18}, // 00b9 - {0.705078f, 0.738770f, 0.711914f, 0.747559f, -0.1875f, -28.5625f, 13.5625f, 14, 18}, // 00ba - {0.091309f, 0.616211f, 0.099121f, 0.623535f, -0.0625f, -18.1875f, 14.3750f, 16, 15}, // 00bb - {0.478027f, 0.743652f, 0.490234f, 0.757813f, 0.7500f, -28.5625f, 22.1875f, 25, 29}, // 00bc - {0.715820f, 0.706055f, 0.728516f, 0.720215f, 0.7500f, -28.5625f, 23.2500f, 26, 29}, // 00bd - {0.877930f, 0.660156f, 0.892090f, 0.674316f, -0.1875f, -28.5625f, 25.0625f, 29, 29}, // 00be - {0.336426f, 0.813477f, 0.344727f, 0.827637f, -0.5625f, -21.9375f, 14.6875f, 17, 29}, // 00bf - {0.988770f, 0.366699f, 0.999512f, 0.384277f, -1.5000f, -35.0625f, 18.6875f, 22, 36}, // 00c0 - {0.452148f, 0.694824f, 0.462891f, 0.711914f, -1.5000f, -35.0000f, 18.6875f, 22, 35}, // 00c1 - {0.476563f, 0.694824f, 0.487305f, 0.711914f, -1.5000f, -34.8125f, 18.7500f, 22, 35}, // 00c2 - {0.988770f, 0.413574f, 0.999512f, 0.431152f, -1.5000f, -35.1250f, 18.6875f, 22, 36}, // 00c3 - {0.297363f, 0.706543f, 0.308105f, 0.723145f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 00c4 - {0.649902f, 0.689941f, 0.660645f, 0.707520f, -1.5000f, -35.5625f, 18.6875f, 22, 36}, // 00c5 - {0.618164f, 0.602051f, 0.633301f, 0.616211f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 00c6 - {0.989746f, 0.384766f, 0.999512f, 0.402344f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 00c7 - {0.000000f, 0.758789f, 0.008789f, 0.776367f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 00c8 - {0.109863f, 0.764648f, 0.118652f, 0.781738f, 0.3125f, -35.0000f, 16.4375f, 18, 35}, // 00c9 - {0.119141f, 0.764648f, 0.127930f, 0.781738f, 0.3125f, -34.8125f, 16.4375f, 18, 35}, // 00ca - {0.840820f, 0.767090f, 0.849609f, 0.783691f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 00cb - {0.312988f, 0.829102f, 0.318359f, 0.846680f, -2.8750f, -35.0625f, 8.6250f, 11, 36}, // 00cc - {0.318848f, 0.833496f, 0.324219f, 0.850586f, 0.6250f, -35.0000f, 8.6250f, 11, 35}, // 00cd - {0.501953f, 0.806152f, 0.508789f, 0.823242f, -2.4375f, -34.8125f, 8.6250f, 14, 35}, // 00ce - {0.898438f, 0.798828f, 0.905762f, 0.815430f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 00cf - {0.701172f, 0.761230f, 0.711914f, 0.775391f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 00d0 - {0.319824f, 0.696289f, 0.330078f, 0.713867f, 0.3125f, -35.1250f, 20.8125f, 21, 36}, // 00d1 - {0.330566f, 0.696289f, 0.340820f, 0.713867f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 00d2 - {0.661133f, 0.696777f, 0.671387f, 0.714355f, -0.3750f, -35.3125f, 20.1875f, 21, 36}, // 00d3 - {0.899902f, 0.697266f, 0.910156f, 0.714844f, -0.3750f, -35.1250f, 20.1875f, 21, 36}, // 00d4 - {0.068848f, 0.697754f, 0.079102f, 0.715332f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 00d5 - {0.040039f, 0.708496f, 0.050293f, 0.725586f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 00d6 - {0.261230f, 0.838867f, 0.270020f, 0.848633f, -0.7500f, -22.9375f, 16.4375f, 18, 20}, // 00d7 - {0.989258f, 0.585938f, 0.999512f, 0.601074f, -0.3750f, -29.1250f, 20.2500f, 21, 31}, // 00d8 - {0.079590f, 0.697754f, 0.089844f, 0.715332f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 00d9 - {0.090332f, 0.697754f, 0.100586f, 0.715332f, 0.0625f, -34.9375f, 20.1250f, 21, 36}, // 00da - {0.101074f, 0.697754f, 0.111328f, 0.715332f, 0.0625f, -34.8125f, 20.1250f, 21, 36}, // 00db - {0.158691f, 0.708496f, 0.168945f, 0.725586f, 0.0625f, -33.9375f, 20.1250f, 21, 35}, // 00dc - {0.571289f, 0.694824f, 0.582031f, 0.711914f, -1.5625f, -34.9375f, 18.6875f, 22, 35}, // 00dd - {0.499023f, 0.791504f, 0.508301f, 0.805664f, 0.2500f, -28.1875f, 17.7500f, 19, 29}, // 00de - {0.279297f, 0.783203f, 0.288574f, 0.797852f, 0.0625f, -29.6250f, 18.1250f, 19, 30}, // 00df - {0.329102f, 0.786133f, 0.337891f, 0.801270f, -0.7500f, -29.6875f, 16.0625f, 18, 31}, // 00e0 - {0.568359f, 0.796387f, 0.577148f, 0.811035f, -0.7500f, -29.6250f, 16.0625f, 18, 30}, // 00e1 - {0.985352f, 0.796387f, 0.994141f, 0.811035f, -0.7500f, -29.4375f, 16.0625f, 18, 30}, // 00e2 - {0.460938f, 0.786133f, 0.469727f, 0.801270f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 00e3 - {0.031250f, 0.800781f, 0.040039f, 0.814941f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 00e4 - {0.470215f, 0.786133f, 0.479004f, 0.801270f, -0.7500f, -30.1875f, 16.0625f, 18, 31}, // 00e5 - {0.293457f, 0.526855f, 0.306641f, 0.538086f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 00e6 - {0.009766f, 0.806152f, 0.018066f, 0.820801f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 00e7 - {0.148438f, 0.786621f, 0.157227f, 0.801758f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 00e8 - {0.916504f, 0.797363f, 0.925293f, 0.812012f, -0.7500f, -29.6250f, 15.5000f, 18, 30}, // 00e9 - {0.182129f, 0.797852f, 0.190918f, 0.812500f, -0.7500f, -29.4375f, 15.5000f, 18, 30}, // 00ea - {0.074707f, 0.800781f, 0.083496f, 0.814941f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 00eb - {0.498047f, 0.761230f, 0.503418f, 0.775879f, -3.3125f, -29.3750f, 7.8125f, 11, 30}, // 00ec - {0.617188f, 0.807129f, 0.622559f, 0.821777f, 0.1875f, -29.3125f, 7.8125f, 11, 30}, // 00ed - {0.874023f, 0.209473f, 0.880859f, 0.224121f, -2.8750f, -29.1250f, 7.8125f, 14, 30}, // 00ee - {0.833984f, 0.177734f, 0.841309f, 0.191895f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 00ef - {0.289063f, 0.783203f, 0.298340f, 0.797852f, -1.0000f, -29.1875f, 17.5000f, 19, 30}, // 00f0 - {0.493164f, 0.806152f, 0.501465f, 0.820801f, -0.0625f, -29.7500f, 16.8125f, 17, 30}, // 00f1 - {0.880859f, 0.193359f, 0.890137f, 0.208496f, -0.7500f, -29.6875f, 16.7500f, 19, 31}, // 00f2 - {0.537598f, 0.783691f, 0.546875f, 0.798340f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 00f3 - {0.895996f, 0.783691f, 0.905273f, 0.798340f, -0.7500f, -29.4375f, 16.7500f, 19, 30}, // 00f4 - {0.627930f, 0.776367f, 0.637207f, 0.791504f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 00f5 - {0.625000f, 0.791992f, 0.634277f, 0.806152f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 00f6 - {0.147461f, 0.832031f, 0.156738f, 0.842285f, -0.9375f, -23.7500f, 16.9375f, 19, 21}, // 00f7 - {0.792480f, 0.804199f, 0.801758f, 0.817383f, -0.7500f, -24.1250f, 16.7500f, 19, 27}, // 00f8 - {0.925781f, 0.806152f, 0.934082f, 0.820801f, -0.1250f, -29.3125f, 16.7500f, 17, 30}, // 00f9 - {0.347656f, 0.806641f, 0.355957f, 0.821289f, -0.1250f, -29.2500f, 16.7500f, 17, 30}, // 00fa - {0.599609f, 0.806641f, 0.607910f, 0.821289f, -0.1250f, -29.1250f, 16.7500f, 17, 30}, // 00fb - {0.554199f, 0.813477f, 0.562500f, 0.827637f, -0.1250f, -28.1875f, 16.7500f, 17, 29}, // 00fc - {0.182617f, 0.747559f, 0.191895f, 0.765625f, -1.6875f, -29.3125f, 15.0000f, 19, 37}, // 00fd - {0.549805f, 0.750000f, 0.558594f, 0.768066f, 0.0625f, -29.8750f, 16.8750f, 18, 37}, // 00fe - {0.957031f, 0.749512f, 0.966309f, 0.767090f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 00ff -// RANGE: 0x100 - 0x180, start 0xd7 - {0.440918f, 0.707520f, 0.451660f, 0.724121f, -1.5000f, -33.6250f, 18.7500f, 22, 34}, // 0100 - {0.200684f, 0.801270f, 0.209473f, 0.815430f, -0.7500f, -28.2500f, 16.0625f, 18, 29}, // 0101 - {0.027344f, 0.690430f, 0.038086f, 0.708008f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 0102 - {0.172852f, 0.786621f, 0.181641f, 0.801758f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 0103 - {0.736328f, 0.674805f, 0.747559f, 0.692383f, -1.5000f, -28.1875f, 18.6875f, 23, 36}, // 0104 - {0.138672f, 0.784180f, 0.147949f, 0.798828f, -0.7500f, -22.3125f, 16.0625f, 19, 30}, // 0105 - {0.989746f, 0.733398f, 0.999512f, 0.750977f, -0.3125f, -35.3125f, 18.8125f, 20, 36}, // 0106 - {0.622559f, 0.806641f, 0.630859f, 0.821289f, -0.7500f, -29.6250f, 15.4375f, 17, 30}, // 0107 - {0.966309f, 0.735840f, 0.976074f, 0.753418f, -0.3125f, -35.1250f, 18.8125f, 20, 36}, // 0108 - {0.802246f, 0.806641f, 0.810547f, 0.821289f, -0.7500f, -29.4375f, 15.4375f, 17, 30}, // 0109 - {0.822754f, 0.748047f, 0.832520f, 0.765137f, -0.3125f, -34.5000f, 18.8125f, 20, 35}, // 010a - {0.822754f, 0.806641f, 0.831055f, 0.821289f, -0.7500f, -28.8125f, 15.4375f, 17, 30}, // 010b - {0.901855f, 0.736328f, 0.911621f, 0.753906f, -0.3125f, -35.2500f, 18.8125f, 20, 36}, // 010c - {0.859375f, 0.806641f, 0.867676f, 0.821289f, -0.7500f, -29.5000f, 15.4375f, 17, 30}, // 010d - {0.833008f, 0.748047f, 0.842773f, 0.765137f, 0.3125f, -34.9375f, 19.8125f, 20, 35}, // 010e - {0.556641f, 0.129883f, 0.567383f, 0.145020f, -0.6875f, -29.8750f, 16.7500f, 22, 31}, // 010f - {0.729004f, 0.761230f, 0.739746f, 0.775391f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 0110 - {0.921875f, 0.765625f, 0.931641f, 0.780762f, -0.6875f, -29.8750f, 16.7500f, 20, 31}, // 0111 - {0.954590f, 0.767578f, 0.963379f, 0.784180f, 0.3125f, -33.6250f, 16.4375f, 18, 34}, // 0112 - {0.327148f, 0.801758f, 0.335938f, 0.815918f, -0.7500f, -28.3125f, 15.5000f, 18, 29}, // 0113 - {0.503418f, 0.759277f, 0.512207f, 0.776855f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 0114 - {0.308594f, 0.787109f, 0.317383f, 0.802246f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 0115 - {0.292969f, 0.764648f, 0.301758f, 0.781738f, 0.3125f, -34.1875f, 16.4375f, 18, 35}, // 0116 - {0.245117f, 0.797852f, 0.253906f, 0.812500f, -0.7500f, -28.8125f, 15.5000f, 18, 30}, // 0117 - {0.230957f, 0.759766f, 0.239746f, 0.777344f, 0.3125f, -28.1875f, 16.4375f, 18, 36}, // 0118 - {0.456055f, 0.801758f, 0.464844f, 0.815918f, -0.7500f, -22.3125f, 15.5000f, 18, 29}, // 0119 - {0.357422f, 0.764648f, 0.366211f, 0.781738f, 0.3125f, -34.9375f, 16.4375f, 18, 35}, // 011a - {0.278320f, 0.798340f, 0.287109f, 0.812988f, -0.7500f, -29.5625f, 15.5000f, 18, 30}, // 011b - {0.776855f, 0.697754f, 0.787109f, 0.715332f, -0.3125f, -35.1250f, 19.8750f, 21, 36}, // 011c - {0.173340f, 0.750488f, 0.182129f, 0.768555f, -0.6250f, -29.5000f, 16.7500f, 18, 37}, // 011d - {0.169434f, 0.699707f, 0.179688f, 0.717285f, -0.3125f, -35.4375f, 19.8750f, 21, 36}, // 011e - {0.843262f, 0.748047f, 0.852051f, 0.766602f, -0.6250f, -29.8125f, 16.7500f, 18, 38}, // 011f - {0.341309f, 0.708984f, 0.351563f, 0.726074f, -0.3125f, -34.5000f, 19.8750f, 21, 35}, // 0120 - {0.153809f, 0.753418f, 0.162598f, 0.771484f, -0.6250f, -28.8125f, 16.7500f, 18, 37}, // 0121 - {0.117676f, 0.693359f, 0.127930f, 0.711426f, -0.3125f, -28.5000f, 19.8750f, 21, 37}, // 0122 - {0.865723f, 0.738770f, 0.874512f, 0.757813f, -0.6250f, -31.4375f, 16.7500f, 18, 39}, // 0123 - {0.111816f, 0.711914f, 0.122070f, 0.729004f, 0.3125f, -34.8125f, 20.8125f, 21, 35}, // 0124 - {0.173828f, 0.769043f, 0.182129f, 0.786133f, -0.1250f, -34.8125f, 16.6875f, 17, 35}, // 0125 - {0.309082f, 0.745605f, 0.321289f, 0.759766f, -1.5625f, -28.1875f, 20.8125f, 25, 29}, // 0126 - {0.838867f, 0.784180f, 0.848145f, 0.798828f, -2.1250f, -29.9375f, 16.7500f, 19, 30}, // 0127 - {0.992188f, 0.272949f, 0.999512f, 0.290527f, -2.8750f, -35.1250f, 8.5625f, 15, 36}, // 0128 - {0.826660f, 0.193359f, 0.833984f, 0.208008f, -3.2500f, -29.4375f, 7.8125f, 15, 30}, // 0129 - {0.083984f, 0.800781f, 0.091309f, 0.817383f, -3.0000f, -33.6250f, 8.6250f, 15, 34}, // 012a - {0.571777f, 0.826172f, 0.579102f, 0.839844f, -3.4375f, -27.9375f, 7.8125f, 15, 28}, // 012b - {0.992676f, 0.709473f, 0.999512f, 0.727051f, -2.4375f, -35.1250f, 8.6250f, 14, 36}, // 012c - {0.579590f, 0.826172f, 0.586426f, 0.840820f, -2.8125f, -29.4375f, 7.8750f, 14, 30}, // 012d - {0.494629f, 0.837402f, 0.499512f, 0.854980f, -1.2500f, -28.1875f, 8.6250f, 10, 36}, // 012e - {0.957031f, 0.836914f, 0.961914f, 0.854980f, -1.6875f, -29.9375f, 7.7500f, 10, 37}, // 012f - {0.732422f, 0.675781f, 0.736328f, 0.692871f, 0.3750f, -34.1875f, 8.6250f, 8, 35}, // 0130 - {0.586914f, 0.398438f, 0.590820f, 0.409180f, 0.1875f, -22.0000f, 7.8125f, 8, 22}, // 0131 - {0.321777f, 0.745605f, 0.333984f, 0.759766f, 0.6250f, -28.1875f, 24.9375f, 25, 29}, // 0132 - {0.788086f, 0.763672f, 0.795898f, 0.782227f, 0.1875f, -29.9375f, 15.5625f, 16, 38}, // 0133 - {0.213867f, 0.711914f, 0.224121f, 0.729004f, -1.1250f, -34.5625f, 16.3125f, 21, 35}, // 0134 - {0.992676f, 0.690918f, 0.999512f, 0.708984f, -3.0625f, -28.8750f, 8.0000f, 14, 37}, // 0135 - {0.217285f, 0.693359f, 0.227539f, 0.711426f, 0.3125f, -28.1875f, 18.7500f, 21, 37}, // 0136 - {0.540527f, 0.750000f, 0.549316f, 0.768555f, -0.0625f, -29.9375f, 15.5000f, 18, 38}, // 0137 - {0.626465f, 0.828125f, 0.635742f, 0.838867f, 0.1250f, -22.0000f, 17.0000f, 19, 22}, // 0138 - {0.249512f, 0.765137f, 0.258301f, 0.782227f, 0.3125f, -34.1250f, 16.3750f, 18, 35}, // 0139 - {0.399414f, 0.829102f, 0.404785f, 0.846680f, 0.1875f, -35.2500f, 7.7500f, 11, 36}, // 013a - {0.966797f, 0.753906f, 0.975586f, 0.771973f, 0.3125f, -28.2500f, 16.3750f, 18, 37}, // 013b - {0.679688f, 0.835938f, 0.683594f, 0.854492f, -0.3125f, -29.9375f, 7.7500f, 8, 38}, // 013c - {0.465332f, 0.801758f, 0.474121f, 0.815918f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013d - {0.712402f, 0.761230f, 0.718750f, 0.775879f, 0.1875f, -29.9375f, 7.7500f, 13, 30}, // 013e - {0.733398f, 0.801758f, 0.742188f, 0.815918f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013f - {0.279785f, 0.839355f, 0.285645f, 0.854004f, 0.1875f, -29.9375f, 7.7500f, 12, 30}, // 0140 - {0.804199f, 0.791992f, 0.813477f, 0.806152f, -1.5625f, -28.1875f, 15.3125f, 19, 29}, // 0141 - {0.500000f, 0.839355f, 0.505859f, 0.854004f, -1.5625f, -29.9375f, 8.4375f, 12, 30}, // 0142 - {0.452148f, 0.712402f, 0.462402f, 0.729492f, 0.3125f, -35.0000f, 20.8125f, 21, 35}, // 0143 - {0.934570f, 0.806641f, 0.942871f, 0.821289f, -0.0625f, -29.6250f, 16.8125f, 17, 30}, // 0144 - {0.505859f, 0.701172f, 0.516113f, 0.718750f, 0.3125f, -28.1875f, 20.8125f, 21, 36}, // 0145 - {0.991211f, 0.646973f, 0.999512f, 0.662109f, -0.0625f, -22.3125f, 16.8125f, 17, 31}, // 0146 - {0.476563f, 0.712402f, 0.486816f, 0.729492f, 0.3125f, -34.9375f, 20.8125f, 21, 35}, // 0147 - {0.972656f, 0.806641f, 0.980957f, 0.821289f, -0.0625f, -29.5625f, 16.8125f, 17, 30}, // 0148 - {0.283203f, 0.768066f, 0.292969f, 0.782715f, -2.3125f, -29.8750f, 16.7500f, 20, 30}, // 0149 - {0.516602f, 0.701172f, 0.526855f, 0.718750f, 0.2500f, -28.1875f, 20.6875f, 21, 36}, // 014a - {0.000000f, 0.807129f, 0.008301f, 0.821777f, -0.0625f, -22.3125f, 16.7500f, 17, 30}, // 014b - {0.570313f, 0.712402f, 0.580566f, 0.729492f, -0.3750f, -33.9375f, 20.1875f, 21, 35}, // 014c - {0.860352f, 0.791992f, 0.869629f, 0.806152f, -0.7500f, -28.2500f, 16.7500f, 19, 29}, // 014d - {0.787598f, 0.704102f, 0.797852f, 0.721680f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 014e - {0.807617f, 0.776367f, 0.816895f, 0.791504f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 014f - {0.798340f, 0.704102f, 0.808594f, 0.721680f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 0150 - {0.091309f, 0.784668f, 0.100586f, 0.799316f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 0151 - {0.240234f, 0.259277f, 0.254883f, 0.273438f, -0.4375f, -28.5000f, 28.3125f, 30, 29}, // 0152 - {0.233887f, 0.748047f, 0.249023f, 0.759277f, -0.7500f, -22.2500f, 26.6875f, 31, 23}, // 0153 - {0.921875f, 0.748047f, 0.931641f, 0.765137f, 0.3125f, -35.0000f, 18.9375f, 20, 35}, // 0154 - {0.991699f, 0.826172f, 0.998535f, 0.840820f, -0.0625f, -29.6250f, 10.4375f, 14, 30}, // 0155 - {0.210449f, 0.743164f, 0.220215f, 0.760742f, 0.3125f, -28.1875f, 18.9375f, 20, 36}, // 0156 - {0.075684f, 0.830078f, 0.082031f, 0.845215f, -0.3750f, -22.3125f, 10.4375f, 13, 31}, // 0157 - {0.220703f, 0.748535f, 0.230469f, 0.765625f, 0.3125f, -34.9375f, 18.9375f, 20, 35}, // 0158 - {0.126465f, 0.826660f, 0.133301f, 0.841309f, -0.8750f, -29.5625f, 10.5000f, 14, 30}, // 0159 - {0.251953f, 0.747070f, 0.261719f, 0.764648f, -0.5625f, -35.3125f, 18.1250f, 20, 36}, // 015a - {0.018555f, 0.807129f, 0.026855f, 0.821777f, -0.8750f, -29.5625f, 15.0000f, 17, 30}, // 015b - {0.347168f, 0.747070f, 0.356934f, 0.764648f, -0.5625f, -35.1250f, 18.1250f, 20, 36}, // 015c - {0.209961f, 0.807129f, 0.218262f, 0.821777f, -0.8750f, -29.4375f, 15.0000f, 17, 30}, // 015d - {0.989746f, 0.335449f, 0.999512f, 0.353516f, -0.5625f, -28.5625f, 18.1250f, 20, 37}, // 015e - {0.218750f, 0.807129f, 0.227051f, 0.821777f, -0.8750f, -22.3125f, 15.0000f, 17, 30}, // 015f - {0.572266f, 0.747070f, 0.582031f, 0.764648f, -0.5625f, -35.1875f, 18.1250f, 20, 36}, // 0160 - {0.227539f, 0.807129f, 0.235840f, 0.821777f, -0.8750f, -29.5000f, 15.0000f, 17, 30}, // 0161 - {0.957520f, 0.704102f, 0.967773f, 0.721680f, -1.3750f, -28.1875f, 17.3125f, 21, 36}, // 0162 - {0.351074f, 0.765137f, 0.357422f, 0.782227f, -1.5000f, -26.4375f, 10.1875f, 13, 35}, // 0163 - {0.836426f, 0.712402f, 0.846680f, 0.729492f, -1.3750f, -34.8750f, 17.3125f, 21, 35}, // 0164 - {0.850586f, 0.225586f, 0.857910f, 0.240723f, -1.5000f, -30.1875f, 10.1875f, 15, 31}, // 0165 - {0.401855f, 0.770020f, 0.412109f, 0.784180f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0166 - {0.642090f, 0.493164f, 0.648926f, 0.506348f, -1.9375f, -26.4375f, 10.1875f, 14, 27}, // 0167 - {0.968262f, 0.704102f, 0.978516f, 0.721680f, 0.0625f, -35.0625f, 20.1250f, 21, 36}, // 0168 - {0.236328f, 0.807129f, 0.244629f, 0.821777f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 0169 - {0.607910f, 0.747070f, 0.618164f, 0.763672f, 0.0625f, -33.6250f, 20.1250f, 21, 34}, // 016a - {0.631348f, 0.813477f, 0.639648f, 0.827637f, -0.1250f, -27.9375f, 16.7500f, 17, 29}, // 016b - {0.369629f, 0.704590f, 0.379883f, 0.722168f, 0.0625f, -35.1250f, 20.1250f, 21, 36}, // 016c - {0.254395f, 0.807129f, 0.262695f, 0.821777f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 016d - {0.487793f, 0.704590f, 0.498047f, 0.722168f, 0.0625f, -35.5625f, 20.1250f, 21, 36}, // 016e - {0.839355f, 0.799316f, 0.847656f, 0.814453f, -0.1250f, -29.8125f, 16.7500f, 17, 31}, // 016f - {0.527344f, 0.704590f, 0.537598f, 0.722168f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 0170 - {0.191895f, 0.784668f, 0.201172f, 0.799316f, -0.1250f, -29.3125f, 16.7500f, 19, 30}, // 0171 - {0.538086f, 0.704590f, 0.548340f, 0.722168f, 0.0625f, -28.1875f, 20.1250f, 21, 36}, // 0172 - {0.141113f, 0.802246f, 0.149902f, 0.816406f, -0.1250f, -22.0000f, 16.7500f, 18, 29}, // 0173 - {0.338867f, 0.171387f, 0.353027f, 0.188477f, -1.5000f, -34.8125f, 25.8125f, 29, 35}, // 0174 - {0.180176f, 0.708008f, 0.192383f, 0.722656f, -1.3125f, -29.1250f, 22.0625f, 25, 30}, // 0175 - {0.837402f, 0.694824f, 0.848145f, 0.711914f, -1.5625f, -34.7500f, 18.7500f, 22, 35}, // 0176 - {0.912109f, 0.747559f, 0.921387f, 0.765625f, -1.6875f, -29.1250f, 15.0000f, 19, 37}, // 0177 - {0.682617f, 0.708008f, 0.693359f, 0.724609f, -1.5625f, -33.8750f, 18.7500f, 22, 34}, // 0178 - {0.653320f, 0.755859f, 0.662598f, 0.772949f, -0.6875f, -35.0000f, 16.6875f, 19, 35}, // 0179 - {0.356445f, 0.807129f, 0.364746f, 0.821777f, -0.6875f, -29.3125f, 15.0000f, 17, 30}, // 017a - {0.062500f, 0.756836f, 0.071777f, 0.773926f, -0.6875f, -34.1875f, 16.6875f, 19, 35}, // 017b - {0.440918f, 0.813965f, 0.449219f, 0.828125f, -0.6875f, -28.5000f, 15.0000f, 17, 29}, // 017c - {0.072266f, 0.756836f, 0.081543f, 0.773926f, -0.6875f, -34.9375f, 16.6875f, 19, 35}, // 017d - {0.365234f, 0.807129f, 0.373535f, 0.821777f, -0.6875f, -29.1875f, 15.0000f, 17, 30}, // 017e - {0.878418f, 0.540527f, 0.884277f, 0.555664f, 0.0625f, -30.2500f, 7.6250f, 12, 31}, // 017f -// RANGE: 0x400 - 0x500, start 0x157 - {0.240234f, 0.759766f, 0.249023f, 0.777344f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 0400 - {0.082031f, 0.768066f, 0.090820f, 0.784668f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 0401 - {0.729004f, 0.706055f, 0.741699f, 0.720215f, -1.0625f, -28.1875f, 22.1875f, 26, 29}, // 0402 - {0.341797f, 0.765137f, 0.350586f, 0.782227f, 0.2500f, -35.0000f, 16.3750f, 18, 35}, // 0403 - {0.932129f, 0.778320f, 0.941895f, 0.792480f, -0.0625f, -28.5625f, 19.1875f, 20, 29}, // 0404 - {0.602539f, 0.778809f, 0.612305f, 0.792969f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0405 - {0.238770f, 0.228516f, 0.242676f, 0.242676f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0406 - {0.150391f, 0.802246f, 0.157715f, 0.818848f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 0407 - {0.166992f, 0.802246f, 0.175781f, 0.816406f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 0408 - {0.737305f, 0.351074f, 0.753906f, 0.365234f, -1.2500f, -28.1875f, 31.4375f, 34, 29}, // 0409 - {0.749023f, 0.552246f, 0.764648f, 0.566406f, 0.2500f, -28.1875f, 31.4375f, 32, 29}, // 040a - {0.334473f, 0.745605f, 0.346680f, 0.759766f, -0.8125f, -28.1875f, 23.6875f, 25, 29}, // 040b - {0.976563f, 0.747070f, 0.986816f, 0.763672f, 0.3125f, -33.5000f, 18.8125f, 21, 34}, // 040c - {0.548828f, 0.704590f, 0.559082f, 0.722168f, 0.2500f, -35.0625f, 20.7500f, 21, 36}, // 040d - {0.158203f, 0.690430f, 0.168945f, 0.708008f, -1.3125f, -35.1250f, 18.8750f, 22, 36}, // 040e - {0.000000f, 0.712891f, 0.010254f, 0.729980f, 0.1875f, -28.1875f, 20.7500f, 21, 35}, // 040f - {0.740234f, 0.761230f, 0.750977f, 0.775391f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0410 - {0.828613f, 0.778809f, 0.838379f, 0.792969f, 0.2500f, -28.1875f, 18.6250f, 20, 29}, // 0411 - {0.942383f, 0.778809f, 0.952148f, 0.792969f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0412 - {0.308594f, 0.802734f, 0.317383f, 0.816895f, 0.2500f, -28.1875f, 16.3750f, 18, 29}, // 0413 - {0.912109f, 0.632813f, 0.924316f, 0.649902f, -1.4375f, -28.1875f, 21.7500f, 25, 35}, // 0414 - {0.317871f, 0.802734f, 0.326660f, 0.816895f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0415 - {0.470215f, 0.660645f, 0.484375f, 0.674805f, -1.6875f, -28.1875f, 25.6250f, 29, 29}, // 0416 - {0.751465f, 0.770020f, 0.761719f, 0.784180f, -0.3750f, -28.5000f, 19.6875f, 21, 29}, // 0417 - {0.455078f, 0.770508f, 0.465332f, 0.784668f, 0.2500f, -28.1875f, 20.7500f, 21, 29}, // 0418 - {0.559570f, 0.704590f, 0.569824f, 0.722168f, 0.2500f, -35.1250f, 20.7500f, 21, 36}, // 0419 - {0.550293f, 0.770508f, 0.560547f, 0.784668f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 041a - {0.796387f, 0.761230f, 0.807129f, 0.775391f, -1.2500f, -28.1875f, 20.8125f, 22, 29}, // 041b - {0.726074f, 0.746094f, 0.738281f, 0.760254f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 041c - {0.561035f, 0.770508f, 0.571289f, 0.784668f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 041d - {0.639648f, 0.770508f, 0.649902f, 0.784668f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 041e - {0.762207f, 0.770508f, 0.772461f, 0.784668f, 0.2500f, -28.1875f, 20.8125f, 21, 29}, // 041f - {0.974609f, 0.778809f, 0.984375f, 0.792969f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0420 - {0.044922f, 0.779297f, 0.054688f, 0.793457f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0421 - {0.465820f, 0.771484f, 0.476074f, 0.785645f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0422 - {0.628418f, 0.761719f, 0.639160f, 0.775879f, -1.3125f, -28.1875f, 18.8750f, 22, 29}, // 0423 - {0.399414f, 0.615723f, 0.411133f, 0.629883f, -0.8125f, -28.1875f, 21.2500f, 24, 29}, // 0424 - {0.807617f, 0.761719f, 0.818359f, 0.775879f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0425 - {0.256836f, 0.712891f, 0.267090f, 0.729980f, 3.2500f, -28.2500f, 22.1875f, 21, 35}, // 0426 - {0.215332f, 0.779297f, 0.225098f, 0.793457f, 0.1875f, -28.1875f, 20.3125f, 20, 29}, // 0427 - {0.513184f, 0.304688f, 0.527832f, 0.318848f, 0.1875f, -28.1875f, 30.1250f, 30, 29}, // 0428 - {0.520508f, 0.000000f, 0.536621f, 0.017090f, 0.1875f, -28.2500f, 31.6875f, 33, 35}, // 0429 - {0.062500f, 0.632324f, 0.074219f, 0.646484f, -1.8750f, -28.1875f, 21.2500f, 24, 29}, // 042a - {0.716797f, 0.114746f, 0.730469f, 0.128906f, 0.2500f, -28.1875f, 25.3750f, 28, 29}, // 042b - {0.258789f, 0.779297f, 0.268555f, 0.793457f, 0.2500f, -28.1875f, 18.5625f, 20, 29}, // 042c - {0.269043f, 0.779297f, 0.278809f, 0.793457f, 0.0000f, -28.5625f, 19.2500f, 20, 29}, // 042d - {0.493652f, 0.383789f, 0.507324f, 0.397949f, 0.6250f, -28.5625f, 27.1875f, 28, 29}, // 042e - {0.661133f, 0.779297f, 0.670898f, 0.793457f, -1.8125f, -28.1875f, 17.4375f, 20, 29}, // 042f - {0.456543f, 0.830078f, 0.465332f, 0.841309f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0430 - {0.864746f, 0.776367f, 0.874023f, 0.791504f, -0.7500f, -29.8125f, 16.5000f, 19, 31}, // 0431 - {0.227051f, 0.833496f, 0.235840f, 0.844238f, 0.0625f, -22.0000f, 16.6875f, 18, 22}, // 0432 - {0.491699f, 0.679688f, 0.499023f, 0.690430f, -0.0625f, -22.0000f, 12.4375f, 15, 22}, // 0433 - {0.713379f, 0.776855f, 0.723633f, 0.790527f, -0.8750f, -22.0000f, 19.1250f, 21, 28}, // 0434 - {0.046875f, 0.831543f, 0.055664f, 0.842773f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0435 - {0.116211f, 0.175781f, 0.128906f, 0.186523f, -1.6250f, -22.0000f, 22.6875f, 26, 22}, // 0436 - {0.684082f, 0.831543f, 0.692871f, 0.842773f, -0.5000f, -22.3125f, 16.2500f, 18, 23}, // 0437 - {0.000000f, 0.836914f, 0.008301f, 0.847656f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 0438 - {0.608398f, 0.807129f, 0.616699f, 0.821777f, -0.0625f, -29.4375f, 16.8125f, 17, 30}, // 0439 - {0.354492f, 0.833496f, 0.363281f, 0.844238f, 0.1250f, -22.0000f, 16.5000f, 18, 22}, // 043a - {0.437500f, 0.828613f, 0.446777f, 0.839355f, -1.6250f, -22.0000f, 16.5000f, 19, 22}, // 043b - {0.379395f, 0.058594f, 0.390137f, 0.069336f, 0.1250f, -22.0000f, 22.1875f, 22, 22}, // 043c - {0.208008f, 0.836914f, 0.216309f, 0.847656f, -0.0625f, -22.0000f, 16.7500f, 17, 22}, // 043d - {0.420410f, 0.825195f, 0.429688f, 0.836426f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 043e - {0.216797f, 0.836914f, 0.225098f, 0.847656f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 043f - {0.287598f, 0.798340f, 0.296387f, 0.812988f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0440 - {0.644531f, 0.835938f, 0.652832f, 0.847168f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0441 - {0.405273f, 0.833496f, 0.414063f, 0.844238f, -1.0625f, -21.9375f, 15.3125f, 18, 22}, // 0442 - {0.298828f, 0.784668f, 0.308105f, 0.799316f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0443 - {0.748047f, 0.032227f, 0.761719f, 0.050293f, -0.7500f, -29.8750f, 26.0625f, 28, 37}, // 0444 - {0.008301f, 0.834473f, 0.017090f, 0.845215f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0445 - {0.131348f, 0.799316f, 0.140625f, 0.812988f, -0.0625f, -22.0000f, 17.8125f, 19, 28}, // 0446 - {0.236328f, 0.836914f, 0.244629f, 0.847656f, -0.1875f, -22.0000f, 16.4375f, 17, 22}, // 0447 - {0.409180f, 0.792969f, 0.421387f, 0.803711f, -0.0625f, -22.0000f, 24.0625f, 25, 22}, // 0448 - {0.657715f, 0.714844f, 0.670898f, 0.728027f, -0.0625f, -22.0000f, 25.7500f, 27, 27}, // 0449 - {0.797363f, 0.722168f, 0.808105f, 0.732910f, -1.5000f, -22.0000f, 18.6875f, 22, 22}, // 044a - {0.351074f, 0.782227f, 0.363770f, 0.792969f, 0.5000f, -22.0000f, 23.8750f, 26, 22}, // 044b - {0.485352f, 0.834473f, 0.494141f, 0.845215f, 0.1250f, -22.0000f, 16.3125f, 18, 22}, // 044c - {0.653320f, 0.835938f, 0.661621f, 0.847168f, -0.6875f, -22.2500f, 15.6250f, 17, 23}, // 044d - {0.329102f, 0.774414f, 0.341797f, 0.785645f, 0.1875f, -22.2500f, 24.0000f, 26, 23}, // 044e - {0.920898f, 0.834473f, 0.929688f, 0.845215f, -0.9375f, -22.0000f, 16.7500f, 18, 22}, // 044f - {0.317871f, 0.787109f, 0.326660f, 0.802246f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 0450 - {0.590332f, 0.802734f, 0.599121f, 0.816895f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 0451 - {0.989746f, 0.068848f, 0.999512f, 0.087402f, -2.7500f, -29.9375f, 16.6875f, 20, 38}, // 0452 - {0.498535f, 0.704590f, 0.505859f, 0.719238f, -0.0625f, -29.3125f, 12.4375f, 15, 30}, // 0453 - {0.662109f, 0.835938f, 0.670410f, 0.847168f, -0.7500f, -22.2500f, 15.6875f, 17, 23}, // 0454 - {0.670898f, 0.835938f, 0.679199f, 0.847168f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0455 - {0.872559f, 0.097168f, 0.876465f, 0.111816f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0456 - {0.969238f, 0.647949f, 0.976563f, 0.662109f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 0457 - {0.336426f, 0.828125f, 0.341797f, 0.846680f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 0458 - {0.416016f, 0.767090f, 0.429688f, 0.777832f, -1.3125f, -22.0000f, 25.5000f, 28, 22}, // 0459 - {0.699707f, 0.775879f, 0.712891f, 0.786621f, -0.0625f, -22.0000f, 25.5625f, 27, 22}, // 045a - {0.389648f, 0.784668f, 0.398926f, 0.799316f, -1.8750f, -29.9375f, 16.8125f, 19, 30}, // 045b - {0.338379f, 0.798340f, 0.347168f, 0.812988f, 0.1250f, -29.2500f, 16.5000f, 18, 30}, // 045c - {0.653809f, 0.807129f, 0.662109f, 0.821777f, -0.0625f, -29.3750f, 16.8125f, 17, 30}, // 045d - {0.013184f, 0.748047f, 0.022461f, 0.766113f, -1.6875f, -29.4375f, 15.0000f, 19, 37}, // 045e - {0.586426f, 0.817383f, 0.594727f, 0.831055f, -0.0625f, -22.0000f, 16.8125f, 17, 28}, // 045f - {0.655762f, 0.660645f, 0.669922f, 0.674805f, -0.3750f, -28.5000f, 28.0625f, 29, 29}, // 0460 - {0.367188f, 0.090820f, 0.378906f, 0.101563f, -1.5000f, -22.0000f, 20.6875f, 24, 22}, // 0461 - {0.874512f, 0.763184f, 0.885254f, 0.777344f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 0462 - {0.061523f, 0.774414f, 0.071289f, 0.789063f, -2.1875f, -30.0000f, 16.3125f, 20, 30}, // 0463 - {0.730469f, 0.098633f, 0.743652f, 0.112793f, 0.6250f, -28.5625f, 26.3750f, 27, 29}, // 0464 - {0.128906f, 0.062988f, 0.140625f, 0.074219f, 0.1250f, -22.2500f, 22.1250f, 24, 23}, // 0465 - {0.392578f, 0.755371f, 0.403809f, 0.769531f, -1.5000f, -28.1875f, 18.5625f, 23, 29}, // 0466 - {0.989746f, 0.402832f, 0.999512f, 0.413574f, -1.7500f, -22.0000f, 16.1875f, 20, 22}, // 0467 - {0.161621f, 0.661133f, 0.175781f, 0.675293f, 0.9375f, -28.1875f, 26.8125f, 29, 29}, // 0468 - {0.434082f, 0.792969f, 0.446289f, 0.803711f, 0.7500f, -22.0000f, 23.0000f, 25, 22}, // 0469 - {0.823242f, 0.706055f, 0.835938f, 0.720215f, 0.0000f, -28.1250f, 25.3750f, 26, 29}, // 046a - {0.729492f, 0.816406f, 0.740234f, 0.827148f, -0.0625f, -22.0000f, 21.6250f, 22, 22}, // 046b - {0.841309f, 0.177246f, 0.858398f, 0.191406f, 0.5625f, -28.1250f, 33.6250f, 35, 29}, // 046c - {0.082031f, 0.756836f, 0.096680f, 0.767578f, 0.1875f, -22.0000f, 29.1875f, 30, 22}, // 046d - {0.990723f, 0.145508f, 0.999023f, 0.166504f, -1.2500f, -35.6250f, 15.3125f, 17, 43}, // 046e - {0.991211f, 0.304199f, 0.999512f, 0.322266f, -1.1250f, -29.8750f, 14.6250f, 17, 37}, // 046f - {0.404297f, 0.755371f, 0.415527f, 0.769531f, -0.8125f, -28.1875f, 20.9375f, 23, 29}, // 0470 - {0.384766f, 0.601074f, 0.395996f, 0.615723f, -0.7500f, -22.0000f, 21.3125f, 23, 30}, // 0471 - {0.476563f, 0.771484f, 0.486816f, 0.785645f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 0472 - {0.874512f, 0.825195f, 0.883789f, 0.836426f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 0473 - {0.641602f, 0.755859f, 0.652832f, 0.770020f, -1.6875f, -28.5625f, 18.8125f, 23, 29}, // 0474 - {0.943359f, 0.825195f, 0.952637f, 0.836426f, -1.5000f, -22.2500f, 15.0000f, 19, 23}, // 0475 - {0.175293f, 0.682129f, 0.186523f, 0.699219f, -1.6875f, -34.9375f, 18.8125f, 23, 35}, // 0476 - {0.182617f, 0.766113f, 0.192383f, 0.781250f, -2.2500f, -30.1250f, 15.0000f, 20, 31}, // 0477 - {0.501465f, 0.000000f, 0.520020f, 0.017578f, -0.3750f, -28.5625f, 35.1875f, 38, 36}, // 0478 - {0.715820f, 0.032227f, 0.732910f, 0.046875f, -0.7500f, -22.3125f, 31.7500f, 35, 30}, // 0479 - {0.518066f, 0.750000f, 0.528320f, 0.766113f, -0.3750f, -30.3750f, 20.2500f, 21, 33}, // 047a - {0.508789f, 0.804688f, 0.518066f, 0.817871f, -0.7500f, -24.0625f, 16.7500f, 19, 27}, // 047b - {0.568848f, 0.000000f, 0.583008f, 0.018555f, -0.3750f, -37.2500f, 28.0625f, 29, 38}, // 047c - {0.770020f, 0.272461f, 0.782715f, 0.288086f, -0.4375f, -31.3125f, 24.0625f, 26, 32}, // 047d - {0.387207f, 0.176270f, 0.401367f, 0.193359f, -0.3750f, -33.7500f, 28.0625f, 29, 35}, // 047e - {0.944824f, 0.749512f, 0.956543f, 0.763672f, -1.5000f, -28.5625f, 20.6875f, 24, 29}, // 047f - {0.262207f, 0.748535f, 0.271973f, 0.765625f, -0.3750f, -28.5625f, 18.8125f, 20, 35}, // 0480 - {0.529297f, 0.813965f, 0.537598f, 0.828125f, -0.5625f, -22.3125f, 15.8125f, 17, 29}, // 0481 - {0.691406f, 0.195313f, 0.701172f, 0.208496f, -0.3125f, -26.3125f, 18.4375f, 20, 27}, // 0482 - {0.132324f, 0.186523f, 0.139648f, 0.191406f, 0.1250f, -29.4375f, 14.5625f, 15, 10}, // 0483 - {0.209473f, 0.095703f, 0.216797f, 0.100098f, 0.4375f, -29.8750f, 15.2500f, 15, 9}, // 0484 - {0.169434f, 0.074219f, 0.173340f, 0.079102f, 0.6250f, -31.1250f, 8.6875f, 8, 10}, // 0485 - {0.680176f, 0.451172f, 0.684082f, 0.456055f, 0.6875f, -31.1250f, 9.1875f, 8, 10}, // 0486 - {0.065430f, 0.715820f, 0.078613f, 0.729004f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0487 - {0.600098f, 0.000000f, 0.615723f, 0.016602f, -1.0625f, -28.1875f, 29.7500f, 32, 34}, // 0488 - {0.553223f, 0.000000f, 0.568359f, 0.017578f, -0.8125f, -28.5625f, 28.8125f, 31, 36}, // 0489 - {0.987793f, 0.048340f, 0.999512f, 0.068359f, 0.2500f, -35.1250f, 20.7500f, 24, 41}, // 048a - {0.272461f, 0.748535f, 0.282227f, 0.765625f, -0.0625f, -29.4375f, 16.7500f, 20, 35}, // 048b - {0.443848f, 0.763672f, 0.454590f, 0.777832f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 048c - {0.911621f, 0.722656f, 0.921387f, 0.733398f, -2.4375f, -22.0000f, 16.3125f, 20, 22}, // 048d - {0.671387f, 0.779297f, 0.681152f, 0.793457f, 0.1875f, -28.1875f, 18.6250f, 20, 29}, // 048e - {0.446777f, 0.798828f, 0.455566f, 0.813477f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 048f - {0.430664f, 0.765137f, 0.439453f, 0.782227f, 0.2500f, -34.1250f, 16.3750f, 18, 35}, // 0490 - {0.271973f, 0.826660f, 0.279297f, 0.840332f, -0.0625f, -27.4375f, 13.5000f, 15, 28}, // 0491 - {0.681641f, 0.779297f, 0.691406f, 0.793457f, -2.0625f, -28.1250f, 16.3750f, 20, 29}, // 0492 - {0.295898f, 0.836914f, 0.304199f, 0.847656f, -2.3125f, -22.0000f, 12.4375f, 17, 22}, // 0493 - {0.850098f, 0.779297f, 0.859863f, 0.793457f, 0.2500f, -28.1875f, 17.1250f, 20, 29}, // 0494 - {0.194824f, 0.815918f, 0.203613f, 0.829102f, -0.0625f, -22.0000f, 16.3125f, 18, 27}, // 0495 - {0.616211f, 0.000000f, 0.631348f, 0.017090f, -1.6875f, -28.1875f, 25.5625f, 31, 35}, // 0496 - {0.570313f, 0.019043f, 0.583496f, 0.032715f, -1.6250f, -22.0000f, 22.6875f, 27, 28}, // 0497 - {0.910645f, 0.704590f, 0.920898f, 0.722168f, -0.3750f, -28.5000f, 19.6875f, 21, 36}, // 0498 - {0.535156f, 0.798828f, 0.543945f, 0.813477f, -0.5000f, -22.2500f, 16.2500f, 18, 30}, // 0499 - {0.258789f, 0.695313f, 0.269531f, 0.712402f, 0.3125f, -28.1875f, 18.8125f, 22, 35}, // 049a - {0.554688f, 0.799316f, 0.563965f, 0.812988f, 0.1250f, -22.0000f, 16.5000f, 19, 28}, // 049b - {0.150879f, 0.771973f, 0.161133f, 0.786133f, 0.2500f, -28.1875f, 19.0625f, 21, 29}, // 049c - {0.526855f, 0.828613f, 0.536133f, 0.839355f, 0.1250f, -22.0000f, 16.6250f, 19, 22}, // 049d - {0.117188f, 0.750000f, 0.128906f, 0.764160f, -2.8125f, -28.1875f, 18.8125f, 24, 29}, // 049e - {0.528809f, 0.765137f, 0.539063f, 0.779785f, -2.9375f, -29.9375f, 15.5000f, 21, 30}, // 049f - {0.393555f, 0.661133f, 0.407715f, 0.675293f, -0.7500f, -28.1875f, 25.1875f, 29, 29}, // 04a0 - {0.020020f, 0.782715f, 0.032715f, 0.793457f, -1.0000f, -21.9375f, 21.5625f, 26, 22}, // 04a1 - {0.617676f, 0.687988f, 0.628906f, 0.705078f, 0.3125f, -28.1875f, 20.8125f, 23, 35}, // 04a2 - {0.558105f, 0.785156f, 0.567871f, 0.798828f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04a3 - {0.924805f, 0.632813f, 0.939453f, 0.646973f, 0.3125f, -28.1875f, 28.8750f, 30, 29}, // 04a4 - {0.136719f, 0.816895f, 0.147461f, 0.827637f, -0.0625f, -22.0000f, 21.0000f, 22, 22}, // 04a5 - {0.711426f, 0.602051f, 0.726563f, 0.616211f, 0.2500f, -28.1875f, 30.1875f, 31, 29}, // 04a6 - {0.913574f, 0.691406f, 0.928223f, 0.704102f, -0.0625f, -22.0000f, 25.6250f, 30, 26}, // 04a7 - {0.776855f, 0.763672f, 0.787598f, 0.777832f, -0.3750f, -28.4375f, 20.6875f, 22, 29}, // 04a8 - {0.953125f, 0.825195f, 0.962402f, 0.836426f, -0.7500f, -22.1875f, 16.8750f, 19, 23}, // 04a9 - {0.582520f, 0.747070f, 0.592285f, 0.764648f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 04aa - {0.662598f, 0.807129f, 0.670898f, 0.821777f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 04ab - {0.010742f, 0.713379f, 0.020996f, 0.730469f, -1.3750f, -28.1875f, 17.3125f, 21, 35}, // 04ac - {0.876953f, 0.811035f, 0.885742f, 0.824707f, -1.0625f, -22.0000f, 15.3125f, 18, 28}, // 04ad - {0.932129f, 0.763672f, 0.942871f, 0.777832f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 04ae - {0.000000f, 0.792480f, 0.009277f, 0.806641f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04af - {0.604980f, 0.764160f, 0.615723f, 0.778320f, -1.5625f, -28.1875f, 18.7500f, 22, 29}, // 04b0 - {0.225586f, 0.792480f, 0.234863f, 0.806641f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04b1 - {0.013184f, 0.695801f, 0.023926f, 0.712891f, -1.2500f, -28.1875f, 18.6875f, 22, 35}, // 04b2 - {0.634766f, 0.799316f, 0.644043f, 0.812988f, -1.4375f, -22.0000f, 15.0000f, 19, 28}, // 04b3 - {0.537109f, 0.000000f, 0.552734f, 0.017090f, -1.2500f, -28.1875f, 26.3750f, 32, 35}, // 04b4 - {0.318359f, 0.760254f, 0.329590f, 0.773926f, -1.3125f, -22.0000f, 20.4375f, 23, 28}, // 04b5 - {0.146484f, 0.689453f, 0.157715f, 0.706543f, 0.1875f, -28.1875f, 20.3125f, 23, 35}, // 04b6 - {0.637695f, 0.785156f, 0.647461f, 0.798828f, -0.1875f, -22.0000f, 16.5000f, 20, 28}, // 04b7 - {0.907227f, 0.779297f, 0.916992f, 0.793457f, 0.1875f, -28.1875f, 20.1250f, 20, 29}, // 04b8 - {0.383789f, 0.836914f, 0.392090f, 0.847656f, -0.1875f, -22.0000f, 16.5000f, 17, 22}, // 04b9 - {0.128418f, 0.780273f, 0.138184f, 0.794434f, 2.6875f, -28.1875f, 20.3750f, 20, 29}, // 04ba - {0.419922f, 0.836914f, 0.428223f, 0.847656f, 2.3125f, -22.0625f, 16.5625f, 17, 22}, // 04bb - {0.848633f, 0.706055f, 0.861328f, 0.720215f, -1.5625f, -28.5000f, 24.6250f, 26, 29}, // 04bc - {0.063477f, 0.817383f, 0.073730f, 0.828613f, -2.5625f, -22.2500f, 17.6250f, 21, 23}, // 04bd - {0.986328f, 0.225586f, 0.999023f, 0.243164f, -1.5625f, -28.5000f, 24.6250f, 26, 36}, // 04be - {0.571777f, 0.765137f, 0.582031f, 0.779785f, -2.5625f, -22.3125f, 17.6250f, 21, 30}, // 04bf - {0.254883f, 0.243652f, 0.258789f, 0.257813f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04c0 - {0.733398f, 0.032227f, 0.747559f, 0.049805f, -1.6875f, -35.1250f, 25.6250f, 29, 36}, // 04c1 - {0.886719f, 0.691895f, 0.899414f, 0.706543f, -1.6250f, -29.4375f, 22.6875f, 26, 30}, // 04c2 - {0.022949f, 0.767090f, 0.032715f, 0.782227f, 0.2500f, -28.1875f, 18.6875f, 20, 31}, // 04c3 - {0.760254f, 0.815918f, 0.769043f, 0.829102f, 0.1250f, -22.0000f, 16.5000f, 18, 27}, // 04c4 - {0.895508f, 0.659668f, 0.907715f, 0.676270f, -1.2500f, -28.1875f, 20.8125f, 25, 34}, // 04c5 - {0.524414f, 0.115723f, 0.535156f, 0.129395f, -1.6250f, -22.0000f, 16.5000f, 22, 28}, // 04c6 - {0.671875f, 0.705078f, 0.682129f, 0.722656f, 0.2500f, -28.1875f, 20.8125f, 21, 36}, // 04c7 - {0.671387f, 0.807129f, 0.679688f, 0.821777f, -0.0625f, -22.0000f, 16.7500f, 17, 30}, // 04c8 - {0.465820f, 0.675293f, 0.477539f, 0.691895f, 0.3125f, -28.1875f, 20.8125f, 24, 34}, // 04c9 - {0.761719f, 0.785156f, 0.771484f, 0.798828f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04ca - {0.132813f, 0.749023f, 0.142578f, 0.766113f, 0.1875f, -28.1875f, 20.3125f, 20, 35}, // 04cb - {0.688965f, 0.817383f, 0.697266f, 0.831055f, -0.1875f, -22.0000f, 16.4375f, 17, 28}, // 04cc - {0.665527f, 0.475098f, 0.679199f, 0.491699f, 0.1875f, -28.1875f, 24.8125f, 28, 34}, // 04cd - {0.875000f, 0.749023f, 0.887207f, 0.762695f, 0.1250f, -22.0000f, 22.1875f, 25, 28}, // 04ce - {0.270996f, 0.257813f, 0.274902f, 0.271973f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04cf - {0.247559f, 0.690430f, 0.258301f, 0.708008f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 04d0 - {0.691895f, 0.787109f, 0.700684f, 0.802246f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 04d1 - {0.693848f, 0.708008f, 0.704590f, 0.724609f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 04d2 - {0.691895f, 0.802734f, 0.700684f, 0.816895f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 04d3 - {0.119629f, 0.602539f, 0.134766f, 0.616699f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 04d4 - {0.009277f, 0.766602f, 0.022461f, 0.777832f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 04d5 - {0.369629f, 0.759766f, 0.378418f, 0.777344f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 04d6 - {0.701172f, 0.787109f, 0.709961f, 0.802246f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 04d7 - {0.943359f, 0.764160f, 0.954102f, 0.778320f, -0.6250f, -28.5000f, 21.1875f, 22, 29}, // 04d8 - {0.693359f, 0.831543f, 0.702148f, 0.842773f, 2.2500f, -22.3750f, 15.7500f, 18, 23}, // 04d9 - {0.861816f, 0.708008f, 0.872559f, 0.724609f, -0.6250f, -33.1250f, 21.1875f, 22, 34}, // 04da - {0.235352f, 0.792480f, 0.244629f, 0.806641f, 0.8750f, -28.6250f, 15.7500f, 19, 29}, // 04db - {0.985352f, 0.177246f, 0.999512f, 0.193848f, -1.6875f, -33.9375f, 25.6250f, 29, 34}, // 04dc - {0.941895f, 0.706055f, 0.954590f, 0.720215f, -1.6250f, -28.2500f, 22.6875f, 26, 29}, // 04dd - {0.308594f, 0.713379f, 0.318848f, 0.730469f, -0.3750f, -34.2500f, 19.6875f, 21, 35}, // 04de - {0.701172f, 0.802734f, 0.709961f, 0.816895f, -0.5000f, -28.5625f, 16.2500f, 18, 29}, // 04df - {0.364258f, 0.792480f, 0.373535f, 0.806641f, -0.5000f, -28.1250f, 17.1875f, 19, 29}, // 04e0 - {0.612793f, 0.792480f, 0.622070f, 0.806641f, -0.5000f, -22.0000f, 17.1875f, 19, 29}, // 04e1 - {0.041016f, 0.747559f, 0.051270f, 0.764160f, 0.2500f, -33.6250f, 20.7500f, 21, 34}, // 04e2 - {0.697754f, 0.817383f, 0.706055f, 0.831055f, -0.0625f, -27.9375f, 16.8125f, 17, 28}, // 04e3 - {0.051758f, 0.747559f, 0.062012f, 0.764160f, 0.2500f, -33.9375f, 20.7500f, 21, 34}, // 04e4 - {0.886230f, 0.813965f, 0.894531f, 0.828125f, -0.0625f, -28.2500f, 16.8125f, 17, 29}, // 04e5 - {0.319336f, 0.714355f, 0.329590f, 0.731445f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 04e6 - {0.870117f, 0.792480f, 0.879395f, 0.806641f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 04e7 - {0.963867f, 0.772461f, 0.974121f, 0.786621f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 04e8 - {0.157715f, 0.825684f, 0.166992f, 0.836914f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 04e9 - {0.330078f, 0.714355f, 0.340332f, 0.731445f, -0.3750f, -33.8125f, 20.2500f, 21, 35}, // 04ea - {0.399414f, 0.784668f, 0.408691f, 0.799316f, -0.7500f, -29.0000f, 16.7500f, 19, 30}, // 04eb - {0.420410f, 0.749512f, 0.430176f, 0.766602f, 0.0000f, -34.3125f, 19.2500f, 20, 35}, // 04ec - {0.091797f, 0.814453f, 0.100098f, 0.828613f, -0.6875f, -28.5625f, 15.6250f, 17, 29}, // 04ed - {0.873047f, 0.708008f, 0.883789f, 0.724609f, -1.3125f, -33.6250f, 18.8750f, 22, 34}, // 04ee - {0.887695f, 0.750000f, 0.896973f, 0.767578f, -1.6875f, -28.0000f, 15.0000f, 19, 36}, // 04ef - {0.308594f, 0.695801f, 0.319336f, 0.712891f, -1.3125f, -33.9375f, 18.9375f, 22, 35}, // 04f0 - {0.163574f, 0.750488f, 0.172852f, 0.768066f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 04f1 - {0.387695f, 0.690430f, 0.398438f, 0.708008f, -1.3125f, -35.0000f, 18.8750f, 22, 36}, // 04f2 - {0.618652f, 0.748047f, 0.627930f, 0.766113f, -1.6875f, -29.3750f, 15.0000f, 19, 37}, // 04f3 - {0.282715f, 0.750977f, 0.292480f, 0.767578f, 0.1875f, -33.9375f, 20.3125f, 20, 34}, // 04f4 - {0.186035f, 0.814453f, 0.194336f, 0.828613f, -0.1875f, -28.2500f, 16.4375f, 17, 29}, // 04f5 - {0.582520f, 0.765137f, 0.591309f, 0.782227f, 0.1875f, -28.1875f, 16.3125f, 18, 35}, // 04f6 - {0.729004f, 0.827637f, 0.736328f, 0.841309f, -0.0625f, -22.0000f, 12.4375f, 15, 28}, // 04f7 - {0.409180f, 0.476563f, 0.422852f, 0.493164f, 0.2500f, -33.9375f, 25.3750f, 28, 34}, // 04f8 - {0.228027f, 0.706543f, 0.240723f, 0.720703f, 0.5000f, -28.2500f, 23.8750f, 26, 29}, // 04f9 - {0.705078f, 0.705078f, 0.715332f, 0.722656f, -1.1250f, -28.1875f, 17.6250f, 21, 36}, // 04fa - {0.680176f, 0.807129f, 0.688477f, 0.821777f, -1.1875f, -22.0000f, 12.3750f, 17, 30}, // 04fb - {0.875000f, 0.674805f, 0.886230f, 0.692383f, -1.2500f, -28.1875f, 18.7500f, 23, 36}, // 04fc - {0.071777f, 0.774414f, 0.081543f, 0.789063f, -1.4375f, -22.0000f, 15.0000f, 20, 30}, // 04fd - {0.976074f, 0.764160f, 0.986816f, 0.778320f, -1.3125f, -28.1875f, 18.6875f, 22, 29}, // 04fe - {0.342285f, 0.834961f, 0.351074f, 0.845703f, -1.4375f, -22.0000f, 15.0625f, 18, 22}, // 04ff -// RANGE: 0x2121 - 0x2123, start 0x257 - {0.508789f, 0.796387f, 0.525391f, 0.804199f, 1.0000f, -23.5000f, 35.1875f, 34, 16}, // 2121 - {0.386230f, 0.257813f, 0.395508f, 0.264160f, -0.5000f, -28.1875f, 18.5625f, 19, 13}, // 2122 -// RANGE: 0xfffd - 0xfffe, start 0x259 - {0.485352f, 0.000000f, 0.500977f, 0.023926f, -0.6250f, -39.6875f, 30.1875f, 32, 49}, // fffd -// RANGE: 0x370 - 0x400, start 0x25a - {0.079102f, 0.715820f, 0.092285f, 0.729004f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0370 - {0.092773f, 0.715820f, 0.105957f, 0.729004f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0371 - {0.770020f, 0.715820f, 0.783203f, 0.729004f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0372 - {0.742188f, 0.718750f, 0.755371f, 0.731934f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0373 - {0.324219f, 0.539063f, 0.330566f, 0.544922f, -1.1250f, -25.4375f, 9.2500f, 13, 12}, // 0374 - {0.331055f, 0.539063f, 0.337402f, 0.544922f, -1.1250f, -7.6250f, 9.2500f, 13, 12}, // 0375 - {0.498535f, 0.719238f, 0.511719f, 0.732422f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0376 - {0.512207f, 0.719238f, 0.525391f, 0.732422f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0377 - {0.755859f, 0.719238f, 0.769043f, 0.732422f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0378 - {0.809082f, 0.719238f, 0.822266f, 0.732422f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0379 - {0.318359f, 0.280762f, 0.323242f, 0.285156f, 0.3750f, -2.7500f, 8.3125f, 10, 9}, // 037a - {0.267578f, 0.719727f, 0.280762f, 0.732910f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037b - {0.352051f, 0.719727f, 0.365234f, 0.732910f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037c - {0.581055f, 0.719727f, 0.594238f, 0.732910f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037d - {0.429688f, 0.322266f, 0.433594f, 0.333984f, 0.5000f, -19.5000f, 8.3125f, 8, 24}, // 037e - {0.609375f, 0.719727f, 0.622559f, 0.732910f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037f - {0.979004f, 0.719727f, 0.992188f, 0.732910f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0380 - {0.050781f, 0.720215f, 0.063965f, 0.733398f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0381 - {0.192871f, 0.720215f, 0.206055f, 0.733398f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0382 - {0.921387f, 0.720215f, 0.934570f, 0.733398f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0383 - {0.234375f, 0.031250f, 0.238281f, 0.035645f, 0.6250f, -26.0625f, 8.3125f, 8, 9}, // 0384 - {0.688477f, 0.520996f, 0.695313f, 0.525391f, -2.8125f, -26.0625f, 8.3125f, 14, 9}, // 0385 - {0.987305f, 0.751465f, 0.999512f, 0.764648f, -2.0625f, -26.0000f, 20.0000f, 25, 27}, // 0386 - {0.411621f, 0.144043f, 0.415039f, 0.147461f, 0.6875f, -16.0625f, 8.3750f, 7, 7}, // 0387 - {0.663086f, 0.752441f, 0.675293f, 0.765625f, -3.3125f, -26.0625f, 21.1250f, 25, 27}, // 0388 - {0.499023f, 0.180176f, 0.511719f, 0.193359f, -3.3125f, -26.0625f, 22.7500f, 26, 27}, // 0389 - {0.609375f, 0.706055f, 0.615723f, 0.719238f, -3.3125f, -26.0625f, 9.5000f, 13, 27}, // 038a - {0.021484f, 0.720703f, 0.034668f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 038b - {0.241211f, 0.720703f, 0.254395f, 0.733887f, -2.2500f, -26.0625f, 23.3125f, 27, 27}, // 038c - {0.380371f, 0.720703f, 0.393555f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 038d - {0.985840f, 0.243652f, 0.999512f, 0.256836f, -3.3125f, -26.0625f, 22.4375f, 28, 27}, // 038e - {0.642090f, 0.226074f, 0.654785f, 0.239258f, -2.1875f, -26.0625f, 22.7500f, 26, 27}, // 038f - {0.672852f, 0.507813f, 0.679688f, 0.520996f, -3.6875f, -26.0625f, 6.6875f, 14, 27}, // 0390 - {0.097168f, 0.756836f, 0.109375f, 0.769531f, -2.0625f, -25.4375f, 20.0000f, 25, 26}, // 0391 - {0.989258f, 0.354004f, 0.999512f, 0.366699f, 0.2500f, -25.4375f, 20.0625f, 21, 26}, // 0392 - {0.769531f, 0.819336f, 0.778320f, 0.832031f, 0.4375f, -25.4375f, 16.5000f, 18, 26}, // 0393 - {0.192383f, 0.756836f, 0.204590f, 0.769531f, -1.8750f, -25.4375f, 20.4375f, 25, 26}, // 0394 - {0.009766f, 0.792969f, 0.020020f, 0.805664f, 0.3750f, -25.4375f, 20.0000f, 21, 26}, // 0395 - {0.926758f, 0.792969f, 0.937012f, 0.805664f, -1.4375f, -25.4375f, 18.3750f, 21, 26}, // 0396 - {0.351563f, 0.793457f, 0.361816f, 0.806152f, 0.3750f, -25.4375f, 21.6250f, 21, 26}, // 0397 - {0.675781f, 0.752441f, 0.687988f, 0.765625f, -0.6250f, -25.8125f, 23.3125f, 25, 27}, // 0398 - {0.735352f, 0.225098f, 0.738770f, 0.237793f, 0.7500f, -25.4375f, 8.3750f, 7, 26}, // 0399 - {0.817383f, 0.782227f, 0.828125f, 0.794922f, 0.1875f, -25.4375f, 20.0000f, 22, 26}, // 039a - {0.828613f, 0.765625f, 0.840332f, 0.778320f, -1.8750f, -25.4375f, 20.0000f, 24, 26}, // 039b - {0.751465f, 0.756836f, 0.763672f, 0.769531f, 0.3125f, -25.4375f, 25.0625f, 25, 26}, // 039c - {0.602051f, 0.793457f, 0.612305f, 0.806152f, 0.3750f, -25.4375f, 21.6875f, 21, 26}, // 039d - {0.828613f, 0.793457f, 0.838867f, 0.806152f, -0.3750f, -25.4375f, 19.5000f, 21, 26}, // 039e - {0.688477f, 0.752441f, 0.700684f, 0.765625f, -0.6250f, -25.8125f, 23.3125f, 25, 27}, // 039f - {0.937500f, 0.793457f, 0.947754f, 0.806152f, 0.3750f, -25.4375f, 21.6250f, 21, 26}, // 03a0 - {0.974609f, 0.793457f, 0.984863f, 0.806152f, 0.3125f, -25.4375f, 20.0000f, 21, 26}, // 03a1 - {0.594727f, 0.720703f, 0.607910f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03a2 - {0.063477f, 0.804199f, 0.073242f, 0.816895f, -0.6250f, -25.4375f, 18.0625f, 20, 26}, // 03a3 - {0.020508f, 0.793945f, 0.030762f, 0.806641f, -1.3125f, -25.4375f, 18.3750f, 21, 26}, // 03a4 - {0.216309f, 0.766113f, 0.228027f, 0.778809f, -1.8750f, -25.4375f, 20.0625f, 24, 26}, // 03a5 - {0.628418f, 0.748047f, 0.641113f, 0.761230f, -0.6250f, -26.1250f, 24.2500f, 26, 27}, // 03a6 - {0.258789f, 0.766113f, 0.270508f, 0.778809f, -1.9375f, -25.4375f, 20.0000f, 24, 26}, // 03a7 - {0.907715f, 0.462402f, 0.920410f, 0.475098f, -0.6250f, -25.4375f, 24.0625f, 26, 26}, // 03a8 - {0.270996f, 0.766113f, 0.282715f, 0.778809f, -0.4375f, -25.8125f, 22.7500f, 24, 26}, // 03a9 - {0.167480f, 0.833008f, 0.173828f, 0.847656f, -1.9375f, -29.7500f, 8.3125f, 13, 30}, // 03aa - {0.544434f, 0.162109f, 0.556152f, 0.176758f, -1.9375f, -29.7500f, 20.0000f, 24, 30}, // 03ab - {0.544434f, 0.798828f, 0.554199f, 0.812012f, -0.9375f, -26.0625f, 17.3125f, 20, 27}, // 03ac - {0.263672f, 0.825195f, 0.271484f, 0.838379f, -1.1250f, -26.0625f, 13.0625f, 16, 27}, // 03ad - {0.991211f, 0.569824f, 0.999512f, 0.585449f, 0.0625f, -26.0625f, 16.7500f, 17, 32}, // 03ae - {0.566406f, 0.035156f, 0.570313f, 0.048340f, 0.0000f, -26.0625f, 6.6250f, 8, 27}, // 03af - {0.254883f, 0.822266f, 0.263184f, 0.835449f, 0.0625f, -26.0625f, 16.5625f, 17, 27}, // 03b0 - {0.183105f, 0.723145f, 0.192871f, 0.733398f, -0.9375f, -19.8750f, 17.3125f, 20, 21}, // 03b1 - {0.742676f, 0.775879f, 0.751465f, 0.791504f, 0.0000f, -25.8125f, 16.9375f, 18, 32}, // 03b2 - {0.564453f, 0.811523f, 0.573730f, 0.824219f, -1.6250f, -19.5000f, 15.0000f, 19, 26}, // 03b3 - {0.811035f, 0.811523f, 0.820313f, 0.824219f, -0.9375f, -25.4375f, 16.7500f, 19, 26}, // 03b4 - {0.133789f, 0.842285f, 0.141602f, 0.852539f, -1.1250f, -19.8750f, 13.0625f, 16, 21}, // 03b5 - {0.922363f, 0.571777f, 0.930176f, 0.587402f, -0.9375f, -25.4375f, 13.1875f, 16, 32}, // 03b6 - {0.991211f, 0.322754f, 0.999512f, 0.335449f, 0.0625f, -19.8750f, 16.7500f, 17, 26}, // 03b7 - {0.895020f, 0.815918f, 0.903809f, 0.829102f, -0.6250f, -25.8125f, 16.7500f, 18, 27}, // 03b8 - {0.345703f, 0.324707f, 0.349121f, 0.334473f, 0.0000f, -19.5000f, 6.6250f, 7, 20}, // 03b9 - {0.622559f, 0.839355f, 0.631348f, 0.849121f, -0.0625f, -19.5000f, 14.9375f, 18, 20}, // 03ba - {0.981445f, 0.811523f, 0.990723f, 0.824219f, -1.6250f, -25.4375f, 15.0000f, 19, 26}, // 03bb - {0.100586f, 0.823242f, 0.108887f, 0.835938f, 0.0000f, -19.5000f, 16.6250f, 17, 26}, // 03bc - {0.377930f, 0.452637f, 0.387207f, 0.462402f, -1.6250f, -19.5625f, 15.0000f, 19, 20}, // 03bd - {0.761719f, 0.799316f, 0.769531f, 0.815430f, -0.9375f, -25.8125f, 13.0000f, 16, 33}, // 03be - {0.787109f, 0.832031f, 0.796387f, 0.842285f, -0.9375f, -19.8750f, 16.6875f, 19, 21}, // 03bf - {0.447754f, 0.121094f, 0.459473f, 0.130859f, -1.5000f, -19.5625f, 20.3750f, 24, 20}, // 03c0 - {0.419922f, 0.812012f, 0.429199f, 0.824707f, 0.0000f, -19.8750f, 17.1875f, 19, 26}, // 03c1 - {0.365234f, 0.822266f, 0.373535f, 0.835449f, -0.9375f, -19.8750f, 14.1875f, 17, 27}, // 03c2 - {0.395508f, 0.069336f, 0.405762f, 0.079590f, -0.9375f, -20.0625f, 18.6250f, 21, 21}, // 03c3 - {0.677246f, 0.681152f, 0.684570f, 0.690918f, -1.5000f, -19.5625f, 11.5000f, 15, 20}, // 03c4 - {0.453125f, 0.841797f, 0.461426f, 0.851563f, 0.0625f, -19.5000f, 16.5625f, 17, 20}, // 03c5 - {0.422852f, 0.782715f, 0.433594f, 0.795410f, -0.9375f, -19.8750f, 19.5000f, 22, 26}, // 03c6 - {0.409668f, 0.804199f, 0.419434f, 0.816895f, -1.8125f, -19.5000f, 15.6875f, 20, 26}, // 03c7 - {0.581055f, 0.782715f, 0.591797f, 0.795410f, 0.0000f, -19.5000f, 21.8750f, 22, 26}, // 03c8 - {0.370605f, 0.133789f, 0.382813f, 0.143555f, -0.9375f, -19.5000f, 23.0000f, 25, 20}, // 03c9 - {0.414551f, 0.694824f, 0.420898f, 0.707520f, -2.7500f, -25.3125f, 6.6875f, 13, 26}, // 03ca - {0.109375f, 0.823242f, 0.117676f, 0.835938f, 0.0625f, -25.3125f, 16.5625f, 17, 26}, // 03cb - {0.710449f, 0.805664f, 0.719727f, 0.818848f, -0.9375f, -26.0625f, 16.6875f, 19, 27}, // 03cc - {0.604492f, 0.822266f, 0.612793f, 0.835449f, 0.0625f, -26.0625f, 16.5625f, 17, 27}, // 03cd - {0.852539f, 0.752441f, 0.864746f, 0.765625f, -0.9375f, -26.0625f, 23.0000f, 25, 27}, // 03ce - {0.623047f, 0.720703f, 0.636230f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03cf - {0.327148f, 0.816406f, 0.335938f, 0.829590f, 0.0000f, -25.8125f, 16.9375f, 18, 27}, // 03d0 - {0.988770f, 0.431641f, 0.999512f, 0.444824f, -1.3125f, -25.8125f, 18.5000f, 22, 27}, // 03d1 - {0.033203f, 0.775879f, 0.044434f, 0.788574f, -1.8750f, -25.5625f, 18.8750f, 23, 26}, // 03d2 - {0.636719f, 0.720703f, 0.649902f, 0.733887f, -3.3125f, -26.0625f, 21.7500f, 27, 27}, // 03d3 - {0.528809f, 0.750000f, 0.540039f, 0.764648f, -1.8750f, -29.8125f, 18.9375f, 23, 30}, // 03d4 - {0.476074f, 0.098633f, 0.486816f, 0.114258f, -0.9375f, -25.4375f, 19.3125f, 22, 32}, // 03d5 - {0.409668f, 0.020996f, 0.422363f, 0.030762f, -1.4375f, -19.5000f, 23.4375f, 26, 20}, // 03d6 - {0.715820f, 0.720703f, 0.729004f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d7 - {0.822754f, 0.720703f, 0.835938f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d8 - {0.847168f, 0.720703f, 0.860352f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d9 - {0.000000f, 0.696289f, 0.011230f, 0.712402f, -0.5000f, -25.8125f, 21.6250f, 23, 33}, // 03da - {0.935059f, 0.720703f, 0.948242f, 0.733887f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03db - {0.509766f, 0.780273f, 0.518555f, 0.795898f, 0.3750f, -25.4375f, 17.3125f, 18, 32}, // 03dc - {0.224609f, 0.721191f, 0.237793f, 0.734375f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03dd - {0.818848f, 0.765625f, 0.828125f, 0.781738f, -0.6250f, -25.8125f, 17.1250f, 19, 33}, // 03de - {0.281250f, 0.721191f, 0.294434f, 0.734375f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03df - {0.128418f, 0.766602f, 0.139648f, 0.779785f, -1.3125f, -25.8125f, 20.7500f, 23, 27}, // 03e0 - {0.141602f, 0.721680f, 0.154785f, 0.734863f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03e1 - {0.147949f, 0.673340f, 0.160645f, 0.688965f, 0.3750f, -25.4375f, 26.3125f, 26, 32}, // 03e2 - {0.292969f, 0.751465f, 0.305664f, 0.764160f, -0.1250f, -19.5625f, 25.0000f, 26, 26}, // 03e3 - {0.213379f, 0.793945f, 0.223633f, 0.806641f, -0.2500f, -25.6250f, 20.5000f, 21, 26}, // 03e4 - {0.008789f, 0.821289f, 0.017578f, 0.833984f, -0.6250f, -19.6250f, 16.7500f, 18, 26}, // 03e5 - {0.143066f, 0.753418f, 0.153320f, 0.769043f, 0.3750f, -25.4375f, 20.3750f, 21, 32}, // 03e6 - {0.374023f, 0.825684f, 0.383301f, 0.836914f, -1.2500f, -21.6875f, 15.8750f, 19, 23}, // 03e7 - {0.449707f, 0.816406f, 0.458496f, 0.829590f, -0.6250f, -25.8125f, 16.6875f, 18, 27}, // 03e8 - {0.740723f, 0.823242f, 0.749023f, 0.835938f, -0.5625f, -19.8750f, 15.1250f, 17, 26}, // 03e9 - {0.203613f, 0.775879f, 0.214844f, 0.788574f, -1.9375f, -25.4375f, 18.6875f, 23, 26}, // 03ea - {0.459961f, 0.088867f, 0.470703f, 0.098633f, -1.5625f, -19.8750f, 18.0625f, 22, 20}, // 03eb - {0.450195f, 0.785156f, 0.460449f, 0.798340f, -0.1250f, -26.4375f, 18.3125f, 21, 27}, // 03ec - {0.227051f, 0.822266f, 0.237305f, 0.833008f, -0.9375f, -21.2500f, 18.3125f, 21, 22}, // 03ed - {0.430664f, 0.804199f, 0.440430f, 0.816895f, -1.4375f, -25.4375f, 17.0000f, 20, 26}, // 03ee - {0.720215f, 0.817383f, 0.728516f, 0.831055f, -1.6875f, -22.1250f, 12.9375f, 17, 28}, // 03ef - {0.988770f, 0.166992f, 0.999023f, 0.177246f, -1.4375f, -19.8750f, 17.9375f, 21, 21}, // 03f0 - {0.770020f, 0.805664f, 0.779297f, 0.818848f, 0.0000f, -19.8750f, 17.1875f, 19, 27}, // 03f1 - {0.900879f, 0.836426f, 0.909668f, 0.846680f, -0.8125f, -19.8750f, 15.0000f, 18, 21}, // 03f2 - {0.994629f, 0.508789f, 0.999512f, 0.524414f, -3.3750f, -25.5000f, 6.6250f, 10, 32}, // 03f3 - {0.884277f, 0.721680f, 0.897461f, 0.734863f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f4 - {0.423340f, 0.722168f, 0.436523f, 0.735352f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f5 - {0.462891f, 0.722168f, 0.476074f, 0.735352f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f6 - {0.783691f, 0.722168f, 0.796875f, 0.735352f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f7 - {0.948730f, 0.722168f, 0.961914f, 0.735352f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f8 - {0.962402f, 0.722168f, 0.975586f, 0.735352f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f9 - {0.122559f, 0.722656f, 0.135742f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fa - {0.365723f, 0.722656f, 0.378906f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fb - {0.525879f, 0.722656f, 0.539063f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fc - {0.539551f, 0.722656f, 0.552734f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fd - {0.553223f, 0.722656f, 0.566406f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fe - {0.897949f, 0.722656f, 0.911133f, 0.735840f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03ff -// RANGE: 0x590 - 0x600, start 0x2ea - {0.169434f, 0.723145f, 0.182617f, 0.736328f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0590 - {0.781250f, 0.564941f, 0.786133f, 0.568848f, 0.8750f, -2.1250f, 10.8125f, 10, 8}, // 0591 - {0.000000f, 0.624023f, 0.006348f, 0.627441f, -0.8750f, -23.9375f, 10.8125f, 13, 7}, // 0592 - {0.331055f, 0.340332f, 0.335449f, 0.345703f, 1.3125f, -27.6875f, 10.8125f, 9, 11}, // 0593 - {0.996582f, 0.000000f, 0.999512f, 0.004395f, 2.3750f, -25.8750f, 10.8125f, 6, 9}, // 0594 - {0.217285f, 0.095703f, 0.221680f, 0.100098f, 1.1250f, -25.8750f, 10.8125f, 9, 9}, // 0595 - {0.387695f, 0.452637f, 0.392090f, 0.457031f, 1.0625f, -2.7500f, 10.8125f, 9, 9}, // 0596 - {0.411621f, 0.147949f, 0.415039f, 0.151367f, 1.9375f, -23.8750f, 10.8125f, 7, 7}, // 0597 - {0.054688f, 0.627441f, 0.059570f, 0.631348f, 0.4375f, -24.5625f, 10.8125f, 10, 8}, // 0598 - {0.387695f, 0.457520f, 0.392090f, 0.461914f, -2.0000f, -25.6250f, 10.8125f, 9, 9}, // 0599 - {0.696289f, 0.458496f, 0.700195f, 0.462891f, 4.8125f, -2.7500f, 10.8125f, 8, 9}, // 059a - {0.229980f, 0.479492f, 0.234375f, 0.483887f, 1.0625f, -2.7500f, 10.8125f, 9, 9}, // 059b - {0.229980f, 0.484375f, 0.234375f, 0.488770f, 1.0625f, -25.6250f, 10.8125f, 9, 9}, // 059c - {0.459473f, 0.571777f, 0.463867f, 0.576172f, 4.1875f, -25.6250f, 10.8125f, 9, 9}, // 059d - {0.060547f, 0.596680f, 0.066406f, 0.601563f, 1.1875f, -26.5000f, 10.8125f, 12, 10}, // 059e - {0.345703f, 0.446777f, 0.353027f, 0.451172f, -1.6875f, -25.5000f, 10.8125f, 15, 9}, // 059f - {0.459473f, 0.576660f, 0.463867f, 0.581055f, 4.0000f, -25.5000f, 10.8125f, 9, 9}, // 05a0 - {0.048340f, 0.627441f, 0.054199f, 0.631836f, -0.3125f, -25.5000f, 10.8125f, 12, 9}, // 05a1 - {0.294922f, 0.723633f, 0.308105f, 0.736816f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05a2 - {0.757813f, 0.486816f, 0.761719f, 0.490723f, 0.7500f, -2.1250f, 10.8125f, 8, 8}, // 05a3 - {0.903809f, 0.478027f, 0.907715f, 0.482422f, 1.5000f, -2.7500f, 10.8125f, 8, 9}, // 05a4 - {0.459473f, 0.581543f, 0.463867f, 0.585938f, 1.1250f, -2.7500f, 10.8125f, 9, 9}, // 05a5 - {0.066895f, 0.596680f, 0.072754f, 0.601563f, -0.3750f, -3.0000f, 10.8125f, 12, 10}, // 05a6 - {0.757813f, 0.476563f, 0.761719f, 0.481445f, 1.5000f, -3.0000f, 10.8125f, 8, 10}, // 05a7 - {0.350098f, 0.591797f, 0.354492f, 0.596191f, 1.1250f, -25.6250f, 10.8125f, 9, 9}, // 05a8 - {0.350098f, 0.596680f, 0.354492f, 0.601074f, -1.6875f, -25.5000f, 10.8125f, 9, 9}, // 05a9 - {0.912109f, 0.628906f, 0.916992f, 0.632813f, 0.8750f, -2.1250f, 10.8125f, 10, 8}, // 05aa - {0.757813f, 0.481934f, 0.761719f, 0.486328f, 1.5000f, -25.9375f, 10.8125f, 8, 9}, // 05ab - {0.903809f, 0.487305f, 0.907715f, 0.491211f, 0.7500f, -25.3125f, 10.8125f, 8, 8}, // 05ac - {0.380371f, 0.616211f, 0.384766f, 0.620605f, 4.1875f, -2.7500f, 10.8125f, 9, 9}, // 05ad - {0.394531f, 0.631348f, 0.399414f, 0.635254f, -2.0000f, -24.5625f, 10.8125f, 10, 8}, // 05ae - {0.229980f, 0.489258f, 0.233887f, 0.493164f, 1.7500f, -24.3750f, 10.8125f, 8, 8}, // 05af - {0.996582f, 0.004883f, 0.999512f, 0.009277f, 2.3750f, -2.5000f, 10.8125f, 6, 9}, // 05b0 - {0.329102f, 0.634277f, 0.334961f, 0.638672f, -0.4375f, -2.5000f, 10.8125f, 12, 9}, // 05b1 - {0.795898f, 0.573730f, 0.801270f, 0.578125f, 0.0625f, -2.5000f, 10.8125f, 11, 9}, // 05b2 - {0.626465f, 0.632324f, 0.631836f, 0.636719f, 0.0625f, -2.5000f, 10.8125f, 11, 9}, // 05b3 - {0.996582f, 0.014160f, 0.999512f, 0.017090f, 2.3750f, -2.5000f, 10.8125f, 6, 6}, // 05b4 - {0.685547f, 0.160156f, 0.689941f, 0.163086f, 1.0000f, -2.5000f, 10.8125f, 9, 6}, // 05b5 - {0.962402f, 0.617188f, 0.966797f, 0.621582f, 1.0000f, -2.5000f, 10.8125f, 9, 9}, // 05b6 - {0.727539f, 0.079590f, 0.731445f, 0.082520f, 1.5625f, -2.1875f, 10.8125f, 8, 6}, // 05b7 - {0.206543f, 0.224121f, 0.210449f, 0.227539f, 1.5625f, -2.1875f, 10.8125f, 8, 7}, // 05b8 - {0.996582f, 0.017578f, 0.999512f, 0.020508f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05b9 - {0.437012f, 0.724609f, 0.450195f, 0.737793f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ba - {0.478027f, 0.675293f, 0.483887f, 0.679688f, -0.4375f, -2.5000f, 10.8125f, 12, 9}, // 05bb - {0.996582f, 0.020996f, 0.999512f, 0.023926f, 2.3750f, -12.9375f, 10.8125f, 6, 6}, // 05bc - {0.996582f, 0.009766f, 0.999512f, 0.013672f, 2.7500f, -2.1250f, 10.8125f, 6, 8}, // 05bd - {0.182617f, 0.585449f, 0.189453f, 0.588867f, -1.3125f, -19.5625f, 11.0000f, 14, 7}, // 05be - {0.690430f, 0.160156f, 0.694336f, 0.163086f, 1.5625f, -22.6875f, 10.8125f, 8, 6}, // 05bf - {0.632813f, 0.414551f, 0.636230f, 0.426758f, 0.1250f, -21.9375f, 6.7500f, 7, 25}, // 05c0 - {0.996582f, 0.024414f, 0.999512f, 0.027344f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c1 - {0.996582f, 0.027832f, 0.999512f, 0.030762f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c2 - {0.350098f, 0.292480f, 0.354004f, 0.302246f, 0.0625f, -19.5625f, 7.1250f, 8, 20}, // 05c3 - {0.343750f, 0.082031f, 0.346680f, 0.084961f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c4 - {0.671387f, 0.725098f, 0.684570f, 0.738281f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c5 - {0.685059f, 0.725098f, 0.698242f, 0.738281f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c6 - {0.698730f, 0.725098f, 0.711914f, 0.738281f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c7 - {0.860840f, 0.725098f, 0.874023f, 0.738281f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c8 - {0.035156f, 0.726074f, 0.048340f, 0.739258f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c9 - {0.155273f, 0.726074f, 0.168457f, 0.739258f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ca - {0.394043f, 0.728027f, 0.407227f, 0.741211f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cb - {0.407715f, 0.728027f, 0.420898f, 0.741211f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cc - {0.650391f, 0.728516f, 0.663574f, 0.741699f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cd - {0.064453f, 0.729492f, 0.077637f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ce - {0.078125f, 0.729492f, 0.091309f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cf - {0.910156f, 0.839355f, 0.918945f, 0.849121f, -0.2500f, -19.5625f, 17.3125f, 18, 20}, // 05d0 - {0.101074f, 0.836426f, 0.110352f, 0.846191f, -0.8750f, -19.9375f, 16.8750f, 19, 20}, // 05d1 - {0.042480f, 0.843262f, 0.050293f, 0.853027f, -1.4375f, -19.9375f, 12.3125f, 16, 20}, // 05d2 - {0.962402f, 0.839355f, 0.971191f, 0.849121f, -1.3125f, -19.5625f, 15.3750f, 18, 20}, // 05d3 - {0.117676f, 0.839844f, 0.126465f, 0.849609f, 0.1250f, -19.9375f, 17.8125f, 18, 20}, // 05d4 - {0.649902f, 0.663086f, 0.655762f, 0.672852f, -1.5625f, -19.9375f, 9.5000f, 12, 20}, // 05d5 - {0.703613f, 0.525391f, 0.709961f, 0.535645f, -1.1875f, -20.3125f, 9.8125f, 13, 21}, // 05d6 - {0.437012f, 0.839844f, 0.445801f, 0.849609f, 0.1250f, -19.9375f, 17.8125f, 18, 20}, // 05d7 - {0.980469f, 0.836426f, 0.989258f, 0.846680f, 0.0000f, -19.9375f, 17.8125f, 18, 21}, // 05d8 - {0.169434f, 0.690430f, 0.175293f, 0.696777f, -1.5625f, -19.9375f, 9.5000f, 12, 13}, // 05d9 - {0.297363f, 0.823730f, 0.305664f, 0.836426f, -1.4375f, -19.9375f, 15.1875f, 17, 26}, // 05da - {0.490234f, 0.722656f, 0.498535f, 0.732910f, -0.8750f, -19.9375f, 15.8125f, 17, 21}, // 05db - {0.383789f, 0.823730f, 0.392090f, 0.836426f, -1.0625f, -25.5000f, 14.5000f, 17, 26}, // 05dc - {0.527344f, 0.839844f, 0.536133f, 0.849609f, 0.1250f, -19.5625f, 17.8125f, 18, 20}, // 05dd - {0.736816f, 0.836426f, 0.746094f, 0.846191f, -1.1250f, -19.9375f, 17.8125f, 19, 20}, // 05de - {0.801270f, 0.508301f, 0.807129f, 0.520996f, -1.5625f, -19.9375f, 9.5000f, 12, 26}, // 05df - {0.110840f, 0.191406f, 0.116211f, 0.201172f, -0.8750f, -19.9375f, 10.1250f, 11, 20}, // 05e0 - {0.874512f, 0.725098f, 0.884277f, 0.735352f, -1.2500f, -19.9375f, 18.1250f, 20, 21}, // 05e1 - {0.544434f, 0.825684f, 0.553711f, 0.836914f, -1.0625f, -19.5625f, 16.5000f, 19, 23}, // 05e2 - {0.485840f, 0.821289f, 0.494629f, 0.833984f, -0.6875f, -19.9375f, 17.0000f, 18, 26}, // 05e3 - {0.465820f, 0.832520f, 0.475098f, 0.842773f, -0.8750f, -19.9375f, 17.0625f, 19, 21}, // 05e4 - {0.518066f, 0.823730f, 0.526367f, 0.836426f, -0.9375f, -19.5625f, 15.1250f, 17, 26}, // 05e5 - {0.883789f, 0.839844f, 0.892578f, 0.849609f, -0.6875f, -19.5625f, 15.4375f, 18, 20}, // 05e6 - {0.924805f, 0.821289f, 0.933594f, 0.833984f, 0.1250f, -19.5625f, 17.5000f, 18, 26}, // 05e7 - {0.725098f, 0.841797f, 0.733398f, 0.851563f, -1.4375f, -19.9375f, 15.1875f, 17, 20}, // 05e8 - {0.418457f, 0.264648f, 0.429688f, 0.274414f, 0.1250f, -19.6250f, 21.0000f, 23, 20}, // 05e9 - {0.756836f, 0.732910f, 0.767090f, 0.743164f, -1.4375f, -19.9375f, 19.0000f, 21, 21}, // 05ea - {0.091797f, 0.729492f, 0.104980f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05eb - {0.105469f, 0.729492f, 0.118652f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ec - {0.206543f, 0.729492f, 0.219727f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ed - {0.769531f, 0.729492f, 0.782715f, 0.742676f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ee - {0.476563f, 0.729980f, 0.489746f, 0.743164f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ef - {0.335449f, 0.324707f, 0.345215f, 0.334473f, -1.5625f, -19.9375f, 17.6875f, 20, 20}, // 05f0 - {0.320801f, 0.340332f, 0.330566f, 0.350098f, -1.5625f, -19.9375f, 17.6875f, 20, 20}, // 05f1 - {0.989258f, 0.106445f, 0.999023f, 0.112793f, -1.5625f, -19.9375f, 17.6875f, 20, 13}, // 05f2 - {0.375977f, 0.336426f, 0.380859f, 0.342285f, -0.6875f, -23.2500f, 6.5000f, 10, 12}, // 05f3 - {0.367676f, 0.336426f, 0.375488f, 0.342285f, -0.6875f, -23.2500f, 12.3750f, 16, 12}, // 05f4 - {0.566895f, 0.729980f, 0.580078f, 0.743164f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f5 - {0.000000f, 0.730957f, 0.013184f, 0.744141f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f6 - {0.308594f, 0.731934f, 0.321777f, 0.745117f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f7 - {0.322266f, 0.731934f, 0.335449f, 0.745117f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f8 - {0.335938f, 0.731934f, 0.349121f, 0.745117f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f9 - {0.729492f, 0.732422f, 0.742676f, 0.745605f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fa - {0.490234f, 0.732910f, 0.503418f, 0.746094f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fb - {0.503906f, 0.732910f, 0.517090f, 0.746094f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fc - {0.743164f, 0.732910f, 0.756348f, 0.746094f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fd - {0.797363f, 0.732910f, 0.810547f, 0.746094f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fe - {0.254883f, 0.733398f, 0.268066f, 0.746582f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ff -// RANGE: 0x3000 - 0x3040, start 0x35a + {0.947754f, 0.276855f, 0.951660f, 0.291016f, 0.2500f, -28.1875f, 7.8750f, 8, 29}, // 0021 + {0.618164f, 0.083984f, 0.624023f, 0.090332f, 0.1875f, -28.1875f, 11.6875f, 12, 13}, // 0022 + {0.940918f, 0.848145f, 0.950684f, 0.862305f, -1.0625f, -28.1875f, 18.0000f, 20, 29}, // 0023 + {0.321289f, 0.824707f, 0.330078f, 0.842285f, -0.2500f, -32.0000f, 17.3125f, 18, 36}, // 0024 + {0.658691f, 0.811035f, 0.670410f, 0.825195f, -0.3750f, -28.5000f, 22.6875f, 24, 29}, // 0025 + {0.020020f, 0.828613f, 0.030762f, 0.842773f, -0.8750f, -28.5000f, 19.7500f, 22, 29}, // 0026 + {0.333984f, 0.273438f, 0.337891f, 0.279785f, -0.1875f, -28.1875f, 6.8125f, 8, 13}, // 0027 + {0.189941f, 0.890137f, 0.195801f, 0.909180f, -0.0625f, -31.0000f, 10.0625f, 12, 39}, // 0028 + {0.436035f, 0.890625f, 0.441895f, 0.909668f, -1.6250f, -31.0000f, 10.1250f, 12, 39}, // 0029 + {0.631836f, 0.035156f, 0.639160f, 0.042969f, -0.8750f, -21.9375f, 13.1875f, 15, 16}, // 002a + {0.598633f, 0.906250f, 0.607910f, 0.916992f, -0.8750f, -24.0625f, 17.2500f, 19, 22}, // 002b + {0.805176f, 0.209473f, 0.809570f, 0.215820f, -1.0625f, -7.5625f, 6.8750f, 9, 13}, // 002c + {0.705566f, 0.086914f, 0.711914f, 0.090332f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 002d + {0.518555f, 0.482910f, 0.522461f, 0.486816f, 0.3125f, -7.3750f, 8.3125f, 8, 8}, // 002e + {0.927246f, 0.036133f, 0.935059f, 0.051270f, -1.8750f, -28.2500f, 12.1250f, 16, 31}, // 002f + {0.739258f, 0.687012f, 0.748535f, 0.701172f, -0.3125f, -28.5000f, 17.5625f, 19, 29}, // 0030 + {0.882813f, 0.148926f, 0.889160f, 0.163086f, 1.0625f, -28.5625f, 17.5625f, 13, 29}, // 0031 + {0.753418f, 0.701172f, 0.762695f, 0.715332f, -0.2500f, -28.5000f, 17.5000f, 19, 29}, // 0032 + {0.576660f, 0.862305f, 0.585938f, 0.876465f, -0.3750f, -28.5000f, 17.5000f, 19, 29}, // 0033 + {0.057617f, 0.848633f, 0.067383f, 0.862793f, -0.8750f, -28.1875f, 17.5625f, 20, 29}, // 0034 + {0.200195f, 0.875000f, 0.208984f, 0.889160f, 0.1250f, -28.1875f, 17.5000f, 18, 29}, // 0035 + {0.586426f, 0.862305f, 0.595703f, 0.876465f, -0.0625f, -28.5000f, 17.5625f, 19, 29}, // 0036 + {0.606934f, 0.862305f, 0.616211f, 0.876465f, -0.6250f, -28.1875f, 17.5625f, 19, 29}, // 0037 + {0.616699f, 0.862305f, 0.625977f, 0.876465f, -0.5000f, -28.5000f, 17.5625f, 19, 29}, // 0038 + {0.703125f, 0.862305f, 0.712402f, 0.876465f, -0.5625f, -28.5000f, 17.5000f, 19, 29}, // 0039 + {0.705566f, 0.027832f, 0.709473f, 0.038574f, 0.3125f, -21.9375f, 7.9375f, 8, 22}, // 003a + {0.852539f, 0.229004f, 0.856934f, 0.242188f, -0.1875f, -21.9375f, 7.8750f, 9, 27}, // 003b + {0.680664f, 0.724609f, 0.688477f, 0.734375f, -1.0000f, -20.6875f, 15.1250f, 16, 20}, // 003c + {0.130859f, 0.199219f, 0.139160f, 0.206055f, 0.1875f, -20.1250f, 16.9375f, 17, 14}, // 003d + {0.496094f, 0.917969f, 0.504395f, 0.927734f, -0.1250f, -20.5000f, 15.3750f, 17, 20}, // 003e + {0.891602f, 0.116699f, 0.899902f, 0.130859f, -1.2500f, -28.5625f, 14.3750f, 17, 29}, // 003f + {0.124023f, 0.051758f, 0.138184f, 0.069336f, -0.5000f, -27.6250f, 27.5625f, 29, 36}, // 0040 + {0.281250f, 0.828613f, 0.291992f, 0.842773f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0041 + {0.156250f, 0.848633f, 0.166016f, 0.862793f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0042 + {0.975586f, 0.848633f, 0.985352f, 0.862793f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0043 + {0.985840f, 0.848633f, 0.995605f, 0.862793f, 0.3125f, -28.1875f, 19.8125f, 20, 29}, // 0044 + {0.368164f, 0.875000f, 0.376953f, 0.889160f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0045 + {0.473145f, 0.875000f, 0.481934f, 0.889160f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0046 + {0.875000f, 0.681641f, 0.885254f, 0.695801f, -0.3125f, -28.5000f, 19.8750f, 21, 29}, // 0047 + {0.670898f, 0.835938f, 0.681152f, 0.850098f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 0048 + {0.648926f, 0.392090f, 0.652832f, 0.406250f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0049 + {0.816895f, 0.875000f, 0.825684f, 0.889160f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 004a + {0.747070f, 0.835938f, 0.757324f, 0.850098f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 004b + {0.826172f, 0.875000f, 0.834961f, 0.889160f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 004c + {0.000000f, 0.804199f, 0.012207f, 0.818359f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 004d + {0.811523f, 0.835938f, 0.821777f, 0.850098f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 004e + {0.858887f, 0.835938f, 0.869141f, 0.850098f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 004f + {0.000000f, 0.849121f, 0.009766f, 0.863281f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0050 + {0.713867f, 0.491211f, 0.725098f, 0.506836f, -0.3750f, -28.5625f, 20.6250f, 23, 32}, // 0051 + {0.042480f, 0.849121f, 0.052246f, 0.863281f, 0.3125f, -28.1875f, 18.9375f, 20, 29}, // 0052 + {0.131348f, 0.849121f, 0.141113f, 0.863281f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0053 + {0.921875f, 0.835938f, 0.932129f, 0.850098f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0054 + {0.226563f, 0.836426f, 0.236816f, 0.850586f, 0.0625f, -28.1875f, 20.1250f, 21, 29}, // 0055 + {0.187012f, 0.818848f, 0.198242f, 0.833008f, -1.6875f, -28.1875f, 18.6875f, 23, 29}, // 0056 + {0.903320f, 0.084473f, 0.917480f, 0.098633f, -1.5000f, -28.1875f, 25.8125f, 29, 29}, // 0057 + {0.370117f, 0.828613f, 0.380859f, 0.842773f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0058 + {0.775879f, 0.828613f, 0.786621f, 0.842773f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 0059 + {0.106934f, 0.862793f, 0.116211f, 0.876953f, -0.6875f, -28.1875f, 16.6875f, 19, 29}, // 005a + {0.994629f, 0.340820f, 0.999512f, 0.359375f, 0.1250f, -31.8125f, 8.4375f, 10, 38}, // 005b + {0.949707f, 0.084961f, 0.957520f, 0.100098f, -1.6250f, -28.2500f, 12.3750f, 16, 31}, // 005c + {0.107422f, 0.903809f, 0.112305f, 0.922363f, -1.8125f, -31.8125f, 8.3750f, 10, 38}, // 005d + {0.369629f, 0.127930f, 0.376953f, 0.136230f, -1.1250f, -28.2500f, 12.7500f, 15, 17}, // 005e + {0.666504f, 0.199707f, 0.674805f, 0.203125f, -1.8750f, -4.0625f, 13.3125f, 17, 7}, // 005f + {0.032227f, 0.465820f, 0.037598f, 0.470215f, -0.8750f, -29.2500f, 9.8750f, 11, 9}, // 0060 + {0.858398f, 0.637695f, 0.867188f, 0.648926f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0061 + {0.166504f, 0.858887f, 0.175293f, 0.874023f, -0.0625f, -29.8750f, 16.7500f, 18, 31}, // 0062 + {0.778809f, 0.074707f, 0.787109f, 0.085938f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0063 + {0.380371f, 0.858887f, 0.389160f, 0.874023f, -0.6875f, -29.8750f, 16.7500f, 18, 31}, // 0064 + {0.635254f, 0.762207f, 0.644043f, 0.773438f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0065 + {0.908203f, 0.181641f, 0.915039f, 0.196777f, -1.3125f, -30.2500f, 10.0625f, 14, 31}, // 0066 + {0.955566f, 0.541016f, 0.964355f, 0.555664f, -0.6250f, -22.3125f, 16.7500f, 18, 30}, // 0067 + {0.657227f, 0.878418f, 0.665527f, 0.893066f, -0.1250f, -29.9375f, 16.6875f, 17, 30}, // 0068 + {0.884766f, 0.244629f, 0.888672f, 0.259277f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0069 + {0.083496f, 0.899414f, 0.088867f, 0.917969f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 006a + {0.647949f, 0.869629f, 0.656738f, 0.884277f, -0.0625f, -29.9375f, 15.5000f, 18, 30}, // 006b + {0.916504f, 0.260254f, 0.920410f, 0.274902f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 006c + {0.805664f, 0.296387f, 0.818359f, 0.307617f, -0.0625f, -22.3125f, 25.6875f, 26, 23}, // 006d + {0.875488f, 0.104980f, 0.883789f, 0.116211f, -0.0625f, -22.3125f, 16.8125f, 17, 23}, // 006e + {0.842773f, 0.185547f, 0.852051f, 0.196777f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 006f + {0.778320f, 0.871582f, 0.787109f, 0.886230f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0070 + {0.888184f, 0.871582f, 0.896973f, 0.886230f, -0.6875f, -22.2500f, 16.7500f, 18, 30}, // 0071 + {0.770020f, 0.106934f, 0.776367f, 0.118164f, -0.0625f, -22.3125f, 10.4375f, 13, 23}, // 0072 + {0.593262f, 0.704102f, 0.601563f, 0.715332f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0073 + {0.721680f, 0.090820f, 0.728027f, 0.104004f, -1.5000f, -26.4375f, 10.1875f, 13, 27}, // 0074 + {0.883301f, 0.915527f, 0.891602f, 0.926758f, -0.1250f, -21.9375f, 16.7500f, 17, 23}, // 0075 + {0.608398f, 0.906250f, 0.617676f, 0.916992f, -1.5000f, -22.0000f, 15.0000f, 19, 22}, // 0076 + {0.038574f, 0.863770f, 0.050781f, 0.874512f, -1.3750f, -22.0000f, 22.0625f, 25, 22}, // 0077 + {0.826660f, 0.249512f, 0.835449f, 0.260254f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0078 + {0.874023f, 0.276367f, 0.883301f, 0.291016f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0079 + {0.541016f, 0.916016f, 0.549316f, 0.926758f, -0.6875f, -22.0000f, 15.0000f, 17, 22}, // 007a + {0.500977f, 0.888184f, 0.507324f, 0.906250f, -1.1250f, -30.5625f, 10.0000f, 13, 37}, // 007b + {0.996094f, 0.000000f, 0.999512f, 0.016113f, 0.1875f, -28.1875f, 7.4375f, 7, 33}, // 007c + {0.321777f, 0.890625f, 0.328125f, 0.908691f, -1.5000f, -30.5625f, 10.0000f, 13, 37}, // 007d + {0.280273f, 0.090332f, 0.290039f, 0.095703f, -0.1875f, -17.3750f, 19.6250f, 20, 11}, // 007e + {0.959961f, 0.761230f, 0.973145f, 0.774414f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 007f +// RANGE: 0x80 - 0x81, start 0x81 + {0.075195f, 0.761719f, 0.088379f, 0.774902f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0080 +// RANGE: 0xa2 - 0x100, start 0x82 + {0.116699f, 0.872559f, 0.125488f, 0.887207f, -0.7500f, -25.9375f, 16.6875f, 18, 30}, // 00a2 + {0.141602f, 0.862793f, 0.150879f, 0.876953f, -0.7500f, -28.5000f, 17.3750f, 19, 29}, // 00a3 + {0.744141f, 0.507324f, 0.755371f, 0.520020f, -0.5625f, -25.0625f, 21.6875f, 23, 26}, // 00a4 + {0.292480f, 0.836426f, 0.302734f, 0.850586f, -1.5000f, -28.1875f, 18.0000f, 21, 29}, // 00a5 + {0.995605f, 0.180664f, 0.999512f, 0.196777f, 0.0625f, -28.1875f, 7.3750f, 8, 33}, // 00a6 + {0.927734f, 0.756836f, 0.937500f, 0.774902f, -0.5000f, -28.5000f, 18.3750f, 20, 37}, // 00a7 + {0.714355f, 0.054688f, 0.721680f, 0.058594f, 0.5000f, -28.1875f, 15.8125f, 15, 8}, // 00a8 + {0.372070f, 0.574219f, 0.384766f, 0.588379f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00a9 + {0.400879f, 0.031250f, 0.407715f, 0.040039f, -0.1875f, -28.5625f, 13.3125f, 14, 18}, // 00aa + {0.479980f, 0.383789f, 0.487793f, 0.392578f, -0.5625f, -19.1875f, 14.3750f, 16, 18}, // 00ab + {0.292480f, 0.041992f, 0.300293f, 0.047363f, -0.1250f, -17.1875f, 16.3125f, 16, 11}, // 00ac + {0.658691f, 0.215820f, 0.665039f, 0.219238f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 00ad + {0.108887f, 0.749512f, 0.121582f, 0.763672f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00ae + {0.691406f, 0.119141f, 0.698730f, 0.122559f, 0.0625f, -28.1875f, 14.7500f, 15, 7}, // 00af + {0.610840f, 0.100098f, 0.616699f, 0.106445f, 0.0625f, -28.5625f, 11.8750f, 12, 13}, // 00b0 + {0.710449f, 0.663086f, 0.719238f, 0.675781f, -0.5000f, -25.2500f, 16.6250f, 18, 26}, // 00b1 + {0.786133f, 0.118652f, 0.792480f, 0.127441f, -0.3125f, -28.5625f, 12.4375f, 13, 18}, // 00b2 + {0.819336f, 0.038086f, 0.826172f, 0.046875f, -0.4375f, -28.5625f, 12.5625f, 14, 18}, // 00b3 + {0.038086f, 0.465820f, 0.043457f, 0.470215f, -0.1250f, -29.2500f, 10.3125f, 11, 9}, // 00b4 + {0.534180f, 0.888184f, 0.542480f, 0.902344f, 0.1875f, -21.9375f, 17.5000f, 17, 29}, // 00b5 + {0.917480f, 0.068359f, 0.925293f, 0.082520f, -1.0000f, -28.1875f, 15.0625f, 16, 29}, // 00b6 + {0.694336f, 0.497070f, 0.698242f, 0.500977f, 0.4375f, -17.6250f, 8.4375f, 8, 8}, // 00b7 + {0.734375f, 0.278809f, 0.738770f, 0.284668f, -0.3125f, -4.0000f, 7.7500f, 9, 12}, // 00b8 + {0.779297f, 0.134766f, 0.783691f, 0.143555f, -0.6875f, -28.5625f, 8.2500f, 9, 18}, // 00b9 + {0.569824f, 0.064941f, 0.576660f, 0.073730f, -0.1875f, -28.5625f, 13.5625f, 14, 18}, // 00ba + {0.843262f, 0.097168f, 0.851074f, 0.104492f, -0.0625f, -18.1875f, 14.3750f, 16, 15}, // 00bb + {0.079102f, 0.804199f, 0.091309f, 0.818359f, 0.7500f, -28.5625f, 22.1875f, 25, 29}, // 00bc + {0.691406f, 0.750000f, 0.704102f, 0.764160f, 0.7500f, -28.5625f, 23.2500f, 26, 29}, // 00bd + {0.129883f, 0.689453f, 0.144043f, 0.703613f, -0.1875f, -28.5625f, 25.0625f, 29, 29}, // 00be + {0.732910f, 0.890137f, 0.741211f, 0.904297f, -0.5625f, -21.9375f, 14.6875f, 17, 29}, // 00bf + {0.658203f, 0.722656f, 0.668945f, 0.740234f, -1.5000f, -35.0625f, 18.6875f, 22, 36}, // 00c0 + {0.397949f, 0.738281f, 0.408691f, 0.755371f, -1.5000f, -35.0000f, 18.6875f, 22, 35}, // 00c1 + {0.201172f, 0.738770f, 0.211914f, 0.755859f, -1.5000f, -34.8125f, 18.7500f, 22, 35}, // 00c2 + {0.917480f, 0.722656f, 0.928223f, 0.740234f, -1.5000f, -35.1250f, 18.6875f, 22, 36}, // 00c3 + {0.212402f, 0.752930f, 0.223145f, 0.769531f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 00c4 + {0.928711f, 0.722656f, 0.939453f, 0.740234f, -1.5000f, -35.5625f, 18.6875f, 22, 36}, // 00c5 + {0.257813f, 0.632324f, 0.272949f, 0.646484f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 00c6 + {0.841309f, 0.796875f, 0.851074f, 0.814453f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 00c7 + {0.395508f, 0.824707f, 0.404297f, 0.842285f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 00c8 + {0.932129f, 0.824707f, 0.940918f, 0.841797f, 0.3125f, -35.0000f, 16.4375f, 18, 35}, // 00c9 + {0.198730f, 0.828613f, 0.207520f, 0.845703f, 0.3125f, -34.8125f, 16.4375f, 18, 35}, // 00ca + {0.330566f, 0.835938f, 0.339355f, 0.852539f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 00cb + {0.993652f, 0.018066f, 0.999023f, 0.035645f, -2.8750f, -35.0625f, 8.6250f, 11, 36}, // 00cc + {0.994141f, 0.831055f, 0.999512f, 0.848145f, 0.6250f, -35.0000f, 8.6250f, 11, 35}, // 00cd + {0.275879f, 0.890137f, 0.282715f, 0.907227f, -2.4375f, -34.8125f, 8.6250f, 14, 35}, // 00ce + {0.275879f, 0.873047f, 0.283203f, 0.889648f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 00cf + {0.175293f, 0.829102f, 0.186035f, 0.843262f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 00d0 + {0.978027f, 0.741699f, 0.988281f, 0.759277f, 0.3125f, -35.1250f, 20.8125f, 21, 36}, // 00d1 + {0.988770f, 0.741699f, 0.999023f, 0.759277f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 00d2 + {0.000000f, 0.742188f, 0.010254f, 0.759766f, -0.3750f, -35.3125f, 20.1875f, 21, 36}, // 00d3 + {0.303711f, 0.742188f, 0.313965f, 0.759766f, -0.3750f, -35.1250f, 20.1875f, 21, 36}, // 00d4 + {0.767090f, 0.742188f, 0.777344f, 0.759766f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 00d5 + {0.985840f, 0.759766f, 0.996094f, 0.776855f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 00d6 + {0.441406f, 0.916992f, 0.450195f, 0.926758f, -0.7500f, -22.9375f, 16.4375f, 18, 20}, // 00d7 + {0.335938f, 0.820313f, 0.346191f, 0.835449f, -0.3750f, -29.1250f, 20.2500f, 21, 31}, // 00d8 + {0.777832f, 0.742188f, 0.788086f, 0.759766f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 00d9 + {0.788574f, 0.742188f, 0.798828f, 0.759766f, 0.0625f, -34.9375f, 20.1250f, 21, 36}, // 00da + {0.938477f, 0.742188f, 0.948730f, 0.759766f, 0.0625f, -34.8125f, 20.1250f, 21, 36}, // 00db + {0.000000f, 0.760254f, 0.010254f, 0.777344f, 0.0625f, -33.9375f, 20.1250f, 21, 35}, // 00dc + {0.040039f, 0.739746f, 0.050781f, 0.756836f, -1.5625f, -34.9375f, 18.6875f, 22, 35}, // 00dd + {0.256836f, 0.862793f, 0.266113f, 0.876953f, 0.2500f, -28.1875f, 17.7500f, 19, 29}, // 00de + {0.087402f, 0.853027f, 0.096680f, 0.867676f, 0.0625f, -29.6250f, 18.1250f, 19, 30}, // 00df + {0.020020f, 0.859375f, 0.028809f, 0.874512f, -0.7500f, -29.6875f, 16.0625f, 18, 31}, // 00e0 + {0.309570f, 0.872559f, 0.318359f, 0.887207f, -0.7500f, -29.6250f, 16.0625f, 18, 30}, // 00e1 + {0.389648f, 0.872559f, 0.398438f, 0.887207f, -0.7500f, -29.4375f, 16.0625f, 18, 30}, // 00e2 + {0.367676f, 0.859375f, 0.376465f, 0.874512f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 00e3 + {0.186523f, 0.875488f, 0.195313f, 0.889648f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 00e4 + {0.478027f, 0.859375f, 0.486816f, 0.874512f, -0.7500f, -30.1875f, 16.0625f, 18, 31}, // 00e5 + {0.402344f, 0.279297f, 0.415527f, 0.290527f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 00e6 + {0.741211f, 0.878418f, 0.749512f, 0.893066f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 00e7 + {0.819336f, 0.859375f, 0.828125f, 0.874512f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 00e8 + {0.398926f, 0.872559f, 0.407715f, 0.887207f, -0.7500f, -29.6250f, 15.5000f, 18, 30}, // 00e9 + {0.408203f, 0.872559f, 0.416992f, 0.887207f, -0.7500f, -29.4375f, 15.5000f, 18, 30}, // 00ea + {0.722656f, 0.875488f, 0.731445f, 0.889648f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 00eb + {0.550293f, 0.596680f, 0.555664f, 0.611328f, -3.3125f, -29.3750f, 7.8125f, 11, 30}, // 00ec + {0.399902f, 0.916992f, 0.405273f, 0.931641f, 0.1875f, -29.3125f, 7.8125f, 11, 30}, // 00ed + {0.141602f, 0.906250f, 0.148438f, 0.920898f, -2.8750f, -29.1250f, 7.8125f, 14, 30}, // 00ee + {0.868652f, 0.181152f, 0.875977f, 0.195313f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 00ef + {0.339355f, 0.853027f, 0.348633f, 0.867676f, -1.0000f, -29.1875f, 17.5000f, 19, 30}, // 00f0 + {0.804688f, 0.878418f, 0.812988f, 0.893066f, -0.0625f, -29.7500f, 16.8125f, 17, 30}, // 00f1 + {0.567383f, 0.846680f, 0.576660f, 0.861816f, -0.7500f, -29.6875f, 16.7500f, 19, 31}, // 00f2 + {0.652344f, 0.854492f, 0.661621f, 0.869141f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 00f3 + {0.116699f, 0.857422f, 0.125977f, 0.872070f, -0.7500f, -29.4375f, 16.7500f, 19, 30}, // 00f4 + {0.577148f, 0.846680f, 0.586426f, 0.861816f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 00f5 + {0.686523f, 0.862793f, 0.695801f, 0.876953f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 00f6 + {0.316895f, 0.909180f, 0.326172f, 0.919434f, -0.9375f, -23.7500f, 16.9375f, 19, 21}, // 00f7 + {0.990234f, 0.371582f, 0.999512f, 0.384766f, -0.7500f, -24.1250f, 16.7500f, 19, 27}, // 00f8 + {0.848633f, 0.878418f, 0.856934f, 0.893066f, -0.1250f, -29.3125f, 16.7500f, 17, 30}, // 00f9 + {0.907715f, 0.878418f, 0.916016f, 0.893066f, -0.1250f, -29.2500f, 16.7500f, 17, 30}, // 00fa + {0.071777f, 0.878906f, 0.080078f, 0.893555f, -0.1250f, -29.1250f, 16.7500f, 17, 30}, // 00fb + {0.019531f, 0.890625f, 0.027832f, 0.904785f, -0.1250f, -28.1875f, 16.7500f, 17, 29}, // 00fc + {0.326172f, 0.806152f, 0.335449f, 0.824219f, -1.6875f, -29.3125f, 15.0000f, 19, 37}, // 00fd + {0.233887f, 0.817871f, 0.242676f, 0.835938f, 0.0625f, -29.8750f, 16.8750f, 18, 37}, // 00fe + {0.515137f, 0.815430f, 0.524414f, 0.833008f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 00ff +// RANGE: 0x100 - 0x180, start 0xe0 + {0.467773f, 0.752930f, 0.478516f, 0.769531f, -1.5000f, -33.6250f, 18.7500f, 22, 34}, // 0100 + {0.731934f, 0.875488f, 0.740723f, 0.889648f, -0.7500f, -28.2500f, 16.0625f, 18, 29}, // 0101 + {0.000000f, 0.724121f, 0.010742f, 0.741699f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 0102 + {0.828613f, 0.859375f, 0.837402f, 0.874512f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 0103 + {0.988281f, 0.463379f, 0.999512f, 0.480957f, -1.5000f, -28.1875f, 18.6875f, 23, 36}, // 0104 + {0.313477f, 0.857422f, 0.322754f, 0.872070f, -0.7500f, -22.3125f, 16.0625f, 19, 30}, // 0105 + {0.450684f, 0.797363f, 0.460449f, 0.814941f, -0.3125f, -35.3125f, 18.8125f, 20, 36}, // 0106 + {0.209473f, 0.878906f, 0.217773f, 0.893555f, -0.7500f, -29.6250f, 15.4375f, 17, 30}, // 0107 + {0.523926f, 0.797363f, 0.533691f, 0.814941f, -0.3125f, -35.1250f, 18.8125f, 20, 36}, // 0108 + {0.283691f, 0.878906f, 0.291992f, 0.893555f, -0.7500f, -29.4375f, 15.4375f, 17, 30}, // 0109 + {0.362305f, 0.806641f, 0.372070f, 0.823730f, -0.3125f, -34.5000f, 18.8125f, 20, 35}, // 010a + {0.635254f, 0.879395f, 0.643555f, 0.894043f, -0.7500f, -28.8125f, 15.4375f, 17, 30}, // 010b + {0.041016f, 0.800293f, 0.050781f, 0.817871f, -0.3125f, -35.2500f, 18.8125f, 20, 36}, // 010c + {0.835449f, 0.879395f, 0.843750f, 0.894043f, -0.7500f, -29.5000f, 15.4375f, 17, 30}, // 010d + {0.414551f, 0.807129f, 0.424316f, 0.824219f, 0.3125f, -34.9375f, 19.8125f, 20, 35}, // 010e + {0.942383f, 0.815918f, 0.953125f, 0.831055f, -0.6875f, -29.8750f, 16.7500f, 22, 31}, // 010f + {0.824219f, 0.829590f, 0.834961f, 0.843750f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 0110 + {0.989746f, 0.431641f, 0.999512f, 0.446777f, -0.6875f, -29.8750f, 16.7500f, 20, 31}, // 0111 + {0.339844f, 0.835938f, 0.348633f, 0.852539f, 0.3125f, -33.6250f, 16.4375f, 18, 34}, // 0112 + {0.755859f, 0.876465f, 0.764648f, 0.890625f, -0.7500f, -28.3125f, 15.5000f, 18, 29}, // 0113 + {0.404785f, 0.824707f, 0.413574f, 0.842285f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 0114 + {0.190918f, 0.859863f, 0.199707f, 0.875000f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 0115 + {0.975586f, 0.831055f, 0.984375f, 0.848145f, 0.3125f, -34.1875f, 16.4375f, 18, 35}, // 0116 + {0.445313f, 0.872559f, 0.454102f, 0.887207f, -0.7500f, -28.8125f, 15.5000f, 18, 30}, // 0117 + {0.414063f, 0.824707f, 0.422852f, 0.842285f, 0.3125f, -28.1875f, 16.4375f, 18, 36}, // 0118 + {0.234375f, 0.876953f, 0.243164f, 0.891113f, -0.7500f, -22.3125f, 15.5000f, 18, 29}, // 0119 + {0.984863f, 0.831055f, 0.993652f, 0.848145f, 0.3125f, -34.9375f, 16.4375f, 18, 35}, // 011a + {0.767090f, 0.872559f, 0.775879f, 0.887207f, -0.7500f, -29.5625f, 15.5000f, 18, 30}, // 011b + {0.586426f, 0.742676f, 0.596680f, 0.760254f, -0.3125f, -35.1250f, 19.8750f, 21, 36}, // 011c + {0.966309f, 0.819336f, 0.975098f, 0.837402f, -0.6250f, -29.5000f, 16.7500f, 18, 37}, // 011d + {0.660156f, 0.742676f, 0.670410f, 0.760254f, -0.3125f, -35.4375f, 19.8750f, 21, 36}, // 011e + {0.912109f, 0.814941f, 0.920898f, 0.833496f, -0.6250f, -29.8125f, 16.7500f, 18, 38}, // 011f + {0.303223f, 0.760254f, 0.313477f, 0.777344f, -0.3125f, -34.5000f, 19.8750f, 21, 35}, // 0120 + {0.010742f, 0.819824f, 0.019531f, 0.837891f, -0.6250f, -28.8125f, 16.7500f, 18, 37}, // 0121 + {0.214844f, 0.734375f, 0.225098f, 0.752441f, -0.3125f, -28.5000f, 19.8750f, 21, 37}, // 0122 + {0.933105f, 0.805176f, 0.941895f, 0.824219f, -0.6250f, -31.4375f, 16.7500f, 18, 39}, // 0123 + {0.765137f, 0.760254f, 0.775391f, 0.777344f, 0.3125f, -34.8125f, 20.8125f, 21, 35}, // 0124 + {0.254883f, 0.844727f, 0.263184f, 0.861816f, -0.1250f, -34.8125f, 16.6875f, 17, 35}, // 0125 + {0.313477f, 0.804199f, 0.325684f, 0.818359f, -1.5625f, -28.1875f, 20.8125f, 25, 29}, // 0126 + {0.391602f, 0.857422f, 0.400879f, 0.872070f, -2.1250f, -29.9375f, 16.7500f, 19, 30}, // 0127 + {0.360352f, 0.868164f, 0.367676f, 0.885742f, -2.8750f, -35.1250f, 8.5625f, 15, 36}, // 0128 + {0.300293f, 0.902832f, 0.307617f, 0.917480f, -3.2500f, -29.4375f, 7.8125f, 15, 30}, // 0129 + {0.857422f, 0.878418f, 0.864746f, 0.895020f, -3.0000f, -33.6250f, 8.6250f, 15, 34}, // 012a + {0.707520f, 0.123047f, 0.714844f, 0.136719f, -3.4375f, -27.9375f, 7.8125f, 15, 28}, // 012b + {0.715820f, 0.877441f, 0.722656f, 0.895020f, -2.4375f, -35.1250f, 8.6250f, 14, 36}, // 012c + {0.164063f, 0.906250f, 0.170898f, 0.920898f, -2.8125f, -29.4375f, 7.8750f, 14, 30}, // 012d + {0.866211f, 0.915527f, 0.871094f, 0.933105f, -1.2500f, -28.1875f, 8.6250f, 10, 36}, // 012e + {0.788574f, 0.915039f, 0.793457f, 0.933105f, -1.6875f, -29.9375f, 7.7500f, 10, 37}, // 012f + {0.498047f, 0.734863f, 0.501953f, 0.751953f, 0.3750f, -34.1875f, 8.6250f, 8, 35}, // 0130 + {0.836426f, 0.217285f, 0.840332f, 0.228027f, 0.1875f, -22.0000f, 7.8125f, 8, 22}, // 0131 + {0.716797f, 0.804199f, 0.729004f, 0.818359f, 0.6250f, -28.1875f, 24.9375f, 25, 29}, // 0132 + {0.932617f, 0.842285f, 0.940430f, 0.860840f, 0.1875f, -29.9375f, 15.5625f, 16, 38}, // 0133 + {0.775879f, 0.760254f, 0.786133f, 0.777344f, -1.1250f, -34.5625f, 16.3125f, 21, 35}, // 0134 + {0.454590f, 0.872559f, 0.461426f, 0.890625f, -3.0625f, -28.8750f, 8.0000f, 14, 37}, // 0135 + {0.371582f, 0.734375f, 0.381836f, 0.752441f, 0.3125f, -28.1875f, 18.7500f, 21, 37}, // 0136 + {0.524902f, 0.815430f, 0.533691f, 0.833984f, -0.0625f, -29.9375f, 15.5000f, 18, 38}, // 0137 + {0.618164f, 0.906250f, 0.627441f, 0.916992f, 0.1250f, -22.0000f, 17.0000f, 19, 22}, // 0138 + {0.048340f, 0.831543f, 0.057129f, 0.848633f, 0.3125f, -34.1250f, 16.3750f, 18, 35}, // 0139 + {0.366211f, 0.734863f, 0.371582f, 0.752441f, 0.1875f, -35.2500f, 7.7500f, 11, 36}, // 013a + {0.087891f, 0.819824f, 0.096680f, 0.837891f, 0.3125f, -28.2500f, 16.3750f, 18, 37}, // 013b + {0.995605f, 0.907715f, 0.999512f, 0.926270f, -0.3125f, -29.9375f, 7.7500f, 8, 38}, // 013c + {0.574707f, 0.876953f, 0.583496f, 0.891113f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013d + {0.901855f, 0.197754f, 0.908203f, 0.212402f, 0.1875f, -29.9375f, 7.7500f, 13, 30}, // 013e + {0.583984f, 0.876953f, 0.592773f, 0.891113f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013f + {0.476074f, 0.688965f, 0.481934f, 0.703613f, 0.1875f, -29.9375f, 7.7500f, 12, 30}, // 0140 + {0.712891f, 0.862793f, 0.722168f, 0.876953f, -1.5625f, -28.1875f, 15.3125f, 19, 29}, // 0141 + {0.799316f, 0.742188f, 0.805176f, 0.756836f, -1.5625f, -29.9375f, 8.4375f, 12, 30}, // 0142 + {0.786621f, 0.760254f, 0.796875f, 0.777344f, 0.3125f, -35.0000f, 20.8125f, 21, 35}, // 0143 + {0.417480f, 0.879883f, 0.425781f, 0.894531f, -0.0625f, -29.6250f, 16.8125f, 17, 30}, // 0144 + {0.833496f, 0.742676f, 0.843750f, 0.760254f, 0.3125f, -28.1875f, 20.8125f, 21, 36}, // 0145 + {0.923828f, 0.133301f, 0.932129f, 0.148438f, -0.0625f, -22.3125f, 16.8125f, 17, 31}, // 0146 + {0.937988f, 0.760254f, 0.948242f, 0.777344f, 0.3125f, -34.9375f, 20.8125f, 21, 35}, // 0147 + {0.461914f, 0.879883f, 0.470215f, 0.894531f, -0.0625f, -29.5625f, 16.8125f, 17, 30}, // 0148 + {0.774902f, 0.843262f, 0.784668f, 0.857910f, -2.3125f, -29.8750f, 16.7500f, 20, 30}, // 0149 + {0.181152f, 0.743164f, 0.191406f, 0.760742f, 0.2500f, -28.1875f, 20.6875f, 21, 36}, // 014a + {0.218262f, 0.880371f, 0.226563f, 0.895020f, -0.0625f, -22.3125f, 16.7500f, 17, 30}, // 014b + {0.583496f, 0.760742f, 0.593750f, 0.777832f, -0.3750f, -33.9375f, 20.1875f, 21, 35}, // 014c + {0.936523f, 0.862793f, 0.945801f, 0.876953f, -0.7500f, -28.2500f, 16.7500f, 19, 29}, // 014d + {0.225586f, 0.743164f, 0.235840f, 0.760742f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 014e + {0.586914f, 0.846680f, 0.596191f, 0.861816f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 014f + {0.236328f, 0.743164f, 0.246582f, 0.760742f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 0150 + {0.401367f, 0.857422f, 0.410645f, 0.872070f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 0151 + {0.255371f, 0.351563f, 0.270020f, 0.365723f, -0.4375f, -28.5000f, 28.3125f, 30, 29}, // 0152 + {0.147461f, 0.806152f, 0.162598f, 0.817383f, -0.7500f, -22.2500f, 26.6875f, 31, 23}, // 0153 + {0.424805f, 0.807129f, 0.434570f, 0.824219f, 0.3125f, -35.0000f, 18.9375f, 20, 35}, // 0154 + {0.232910f, 0.906250f, 0.239746f, 0.920898f, -0.0625f, -29.6250f, 10.4375f, 14, 30}, // 0155 + {0.187988f, 0.800781f, 0.197754f, 0.818359f, 0.3125f, -28.1875f, 18.9375f, 20, 36}, // 0156 + {0.915039f, 0.165527f, 0.921387f, 0.180664f, -0.3750f, -22.3125f, 10.4375f, 13, 31}, // 0157 + {0.851563f, 0.807129f, 0.861328f, 0.824219f, 0.3125f, -34.9375f, 18.9375f, 20, 35}, // 0158 + {0.240234f, 0.906250f, 0.247070f, 0.920898f, -0.8750f, -29.5625f, 10.5000f, 14, 30}, // 0159 + {0.637695f, 0.801758f, 0.647461f, 0.819336f, -0.5625f, -35.3125f, 18.1250f, 20, 36}, // 015a + {0.482422f, 0.880371f, 0.490723f, 0.895020f, -0.8750f, -29.5625f, 15.0000f, 17, 30}, // 015b + {0.803223f, 0.803223f, 0.812988f, 0.820801f, -0.5625f, -35.1250f, 18.1250f, 20, 36}, // 015c + {0.092773f, 0.881348f, 0.101074f, 0.895996f, -0.8750f, -29.4375f, 15.0000f, 17, 30}, // 015d + {0.328125f, 0.758301f, 0.337891f, 0.776367f, -0.5625f, -28.5625f, 18.1250f, 20, 37}, // 015e + {0.795898f, 0.883789f, 0.804199f, 0.898438f, -0.8750f, -22.3125f, 15.0000f, 17, 30}, // 015f + {0.298828f, 0.805176f, 0.308594f, 0.822754f, -0.5625f, -35.1875f, 18.1250f, 20, 36}, // 0160 + {0.080566f, 0.884277f, 0.088867f, 0.898926f, -0.8750f, -29.5000f, 15.0000f, 17, 30}, // 0161 + {0.409180f, 0.743164f, 0.419434f, 0.760742f, -1.3750f, -28.1875f, 17.3125f, 21, 36}, // 0162 + {0.925781f, 0.891602f, 0.932129f, 0.908691f, -1.5000f, -26.4375f, 10.1875f, 13, 35}, // 0163 + {0.655762f, 0.760742f, 0.666016f, 0.777832f, -1.3750f, -34.8750f, 17.3125f, 21, 35}, // 0164 + {0.960938f, 0.052734f, 0.968262f, 0.067871f, -1.5000f, -30.1875f, 10.1875f, 15, 31}, // 0165 + {0.734863f, 0.836426f, 0.745117f, 0.850586f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0166 + {0.714844f, 0.106934f, 0.721680f, 0.120117f, -1.9375f, -26.4375f, 10.1875f, 14, 27}, // 0167 + {0.419922f, 0.743164f, 0.430176f, 0.760742f, 0.0625f, -35.0625f, 20.1250f, 21, 36}, // 0168 + {0.329102f, 0.884277f, 0.337402f, 0.898926f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 0169 + {0.764648f, 0.805176f, 0.774902f, 0.821777f, 0.0625f, -33.6250f, 20.1250f, 21, 34}, // 016a + {0.750000f, 0.891113f, 0.758301f, 0.905273f, -0.1250f, -27.9375f, 16.7500f, 17, 29}, // 016b + {0.559570f, 0.744141f, 0.569824f, 0.761719f, 0.0625f, -35.1250f, 20.1250f, 21, 36}, // 016c + {0.337891f, 0.884277f, 0.346191f, 0.898926f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 016d + {0.633301f, 0.744141f, 0.643555f, 0.761719f, 0.0625f, -35.5625f, 20.1250f, 21, 36}, // 016e + {0.897461f, 0.648438f, 0.905762f, 0.663574f, -0.1250f, -29.8125f, 16.7500f, 17, 31}, // 016f + {0.817383f, 0.744141f, 0.827637f, 0.761719f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 0170 + {0.411133f, 0.857422f, 0.420410f, 0.872070f, -0.1250f, -29.3125f, 16.7500f, 19, 30}, // 0171 + {0.949219f, 0.744141f, 0.959473f, 0.761719f, 0.0625f, -28.1875f, 20.1250f, 21, 36}, // 0172 + {0.606934f, 0.876953f, 0.615723f, 0.891113f, -0.1250f, -22.0000f, 16.7500f, 18, 29}, // 0173 + {0.033203f, 0.191406f, 0.047363f, 0.208496f, -1.5000f, -34.8125f, 25.8125f, 29, 35}, // 0174 + {0.542969f, 0.751953f, 0.555176f, 0.766602f, -1.3125f, -29.1250f, 22.0625f, 25, 30}, // 0175 + {0.152832f, 0.739746f, 0.163574f, 0.756836f, -1.5625f, -34.7500f, 18.7500f, 22, 35}, // 0176 + {0.395020f, 0.806152f, 0.404297f, 0.824219f, -1.6875f, -29.1250f, 15.0000f, 19, 37}, // 0177 + {0.498047f, 0.752930f, 0.508789f, 0.769531f, -1.5625f, -33.8750f, 18.7500f, 22, 34}, // 0178 + {0.557617f, 0.819824f, 0.566895f, 0.836914f, -0.6875f, -35.0000f, 16.6875f, 19, 35}, // 0179 + {0.346680f, 0.884277f, 0.354980f, 0.898926f, -0.6875f, -29.3125f, 15.0000f, 17, 30}, // 017a + {0.636719f, 0.819824f, 0.645996f, 0.836914f, -0.6875f, -34.1875f, 16.6875f, 19, 35}, // 017b + {0.941895f, 0.891113f, 0.950195f, 0.905273f, -0.6875f, -28.5000f, 15.0000f, 17, 29}, // 017c + {0.876465f, 0.819824f, 0.885742f, 0.836914f, -0.6875f, -34.9375f, 16.6875f, 19, 35}, // 017d + {0.552734f, 0.884277f, 0.561035f, 0.898926f, -0.6875f, -29.1875f, 15.0000f, 17, 30}, // 017e + {0.907227f, 0.602539f, 0.913086f, 0.617676f, 0.0625f, -30.2500f, 7.6250f, 12, 31}, // 017f +// RANGE: 0x400 - 0x500, start 0x160 + {0.423340f, 0.824707f, 0.432129f, 0.842285f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 0400 + {0.646484f, 0.835938f, 0.655273f, 0.852539f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 0401 + {0.164063f, 0.750488f, 0.176758f, 0.764648f, -1.0625f, -28.1875f, 22.1875f, 26, 29}, // 0402 + {0.137207f, 0.831543f, 0.145996f, 0.848633f, 0.2500f, -35.0000f, 16.3750f, 18, 35}, // 0403 + {0.207520f, 0.849121f, 0.217285f, 0.863281f, -0.0625f, -28.5625f, 19.1875f, 20, 29}, // 0404 + {0.237305f, 0.849121f, 0.247070f, 0.863281f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0405 + {0.680176f, 0.408203f, 0.684082f, 0.422363f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0406 + {0.227051f, 0.880371f, 0.234375f, 0.896973f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 0407 + {0.616211f, 0.876953f, 0.625000f, 0.891113f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 0408 + {0.398438f, 0.371094f, 0.415039f, 0.385254f, -1.2500f, -28.1875f, 31.4375f, 34, 29}, // 0409 + {0.275391f, 0.577637f, 0.291016f, 0.591797f, 0.2500f, -28.1875f, 31.4375f, 32, 29}, // 040a + {0.729492f, 0.804199f, 0.741699f, 0.818359f, -0.8125f, -28.1875f, 23.6875f, 25, 29}, // 040b + {0.647949f, 0.805664f, 0.658203f, 0.822266f, 0.3125f, -33.5000f, 18.8125f, 21, 34}, // 040c + {0.732910f, 0.745117f, 0.743164f, 0.762695f, 0.2500f, -35.0625f, 20.7500f, 21, 36}, // 040d + {0.939941f, 0.724121f, 0.950684f, 0.741699f, -1.3125f, -35.1250f, 18.8750f, 22, 36}, // 040e + {0.828125f, 0.760742f, 0.838379f, 0.777832f, 0.1875f, -28.1875f, 20.7500f, 21, 35}, // 040f + {0.835449f, 0.829590f, 0.846191f, 0.843750f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0410 + {0.757813f, 0.849121f, 0.767578f, 0.863281f, 0.2500f, -28.1875f, 18.6250f, 20, 29}, // 0411 + {0.067871f, 0.849609f, 0.077637f, 0.863770f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0412 + {0.696289f, 0.876953f, 0.705078f, 0.891113f, 0.2500f, -28.1875f, 16.3750f, 18, 29}, // 0413 + {0.787598f, 0.663574f, 0.799805f, 0.680664f, -1.4375f, -28.1875f, 21.7500f, 25, 35}, // 0414 + {0.922852f, 0.876953f, 0.931641f, 0.891113f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0415 + {0.586914f, 0.689453f, 0.601074f, 0.703613f, -1.6875f, -28.1875f, 25.6250f, 29, 29}, // 0416 + {0.798340f, 0.836914f, 0.808594f, 0.851074f, -0.3750f, -28.5000f, 19.6875f, 21, 29}, // 0417 + {0.349121f, 0.837402f, 0.359375f, 0.851563f, 0.2500f, -28.1875f, 20.7500f, 21, 29}, // 0418 + {0.743652f, 0.745117f, 0.753906f, 0.762695f, 0.2500f, -35.1250f, 20.7500f, 21, 36}, // 0419 + {0.359863f, 0.837402f, 0.370117f, 0.851563f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 041a + {0.125977f, 0.830078f, 0.136719f, 0.844238f, -1.2500f, -28.1875f, 20.8125f, 22, 29}, // 041b + {0.270020f, 0.804688f, 0.282227f, 0.818848f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 041c + {0.556641f, 0.837402f, 0.566895f, 0.851563f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 041d + {0.634766f, 0.837402f, 0.645020f, 0.851563f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 041e + {0.869629f, 0.837402f, 0.879883f, 0.851563f, 0.2500f, -28.1875f, 20.8125f, 21, 29}, // 041f + {0.303223f, 0.849609f, 0.312988f, 0.863770f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0420 + {0.596680f, 0.849609f, 0.606445f, 0.863770f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0421 + {0.964844f, 0.837891f, 0.975098f, 0.852051f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0422 + {0.254395f, 0.830078f, 0.265137f, 0.844238f, -1.3125f, -28.1875f, 18.8750f, 22, 29}, // 0423 + {0.025391f, 0.813965f, 0.037109f, 0.828125f, -0.8125f, -28.1875f, 21.2500f, 24, 29}, // 0424 + {0.534180f, 0.830078f, 0.544922f, 0.844238f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0425 + {0.876465f, 0.760742f, 0.886719f, 0.777832f, 3.2500f, -28.2500f, 22.1875f, 21, 35}, // 0426 + {0.906738f, 0.849609f, 0.916504f, 0.863770f, 0.1875f, -28.1875f, 20.3125f, 20, 29}, // 0427 + {0.849121f, 0.665527f, 0.863770f, 0.679688f, 0.1875f, -28.1875f, 30.1250f, 30, 29}, // 0428 + {0.977051f, 0.018066f, 0.993164f, 0.035156f, 0.1875f, -28.2500f, 31.6875f, 33, 35}, // 0429 + {0.372559f, 0.813965f, 0.384277f, 0.828125f, -1.8750f, -28.1875f, 21.2500f, 24, 29}, // 042a + {0.027832f, 0.706543f, 0.041504f, 0.720703f, 0.2500f, -28.1875f, 25.3750f, 28, 29}, // 042b + {0.180664f, 0.850098f, 0.190430f, 0.864258f, 0.2500f, -28.1875f, 18.5625f, 20, 29}, // 042c + {0.880371f, 0.850098f, 0.890137f, 0.864258f, 0.0000f, -28.5625f, 19.2500f, 20, 29}, // 042d + {0.356934f, 0.707031f, 0.370605f, 0.721191f, 0.6250f, -28.5625f, 27.1875f, 28, 29}, // 042e + {0.666504f, 0.850586f, 0.676270f, 0.864746f, -1.8125f, -28.1875f, 17.4375f, 20, 29}, // 042f + {0.414063f, 0.908203f, 0.422852f, 0.919434f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0430 + {0.609863f, 0.846680f, 0.619141f, 0.861816f, -0.7500f, -29.8125f, 16.5000f, 19, 31}, // 0431 + {0.070313f, 0.912598f, 0.079102f, 0.923340f, 0.0625f, -22.0000f, 16.6875f, 18, 22}, // 0432 + {0.698242f, 0.043945f, 0.705566f, 0.054688f, -0.0625f, -22.0000f, 12.4375f, 15, 22}, // 0433 + {0.031738f, 0.847656f, 0.041992f, 0.861328f, -0.8750f, -22.0000f, 19.1250f, 21, 28}, // 0434 + {0.460449f, 0.908203f, 0.469238f, 0.919434f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0435 + {0.867676f, 0.852051f, 0.880371f, 0.862793f, -1.6250f, -22.0000f, 22.6875f, 26, 22}, // 0436 + {0.211914f, 0.908691f, 0.220703f, 0.919922f, -0.5000f, -22.3125f, 16.2500f, 18, 23}, // 0437 + {0.969238f, 0.916016f, 0.977539f, 0.926758f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 0438 + {0.644043f, 0.884766f, 0.652344f, 0.899414f, -0.0625f, -29.4375f, 16.8125f, 17, 30}, // 0439 + {0.326660f, 0.912598f, 0.335449f, 0.923340f, 0.1250f, -22.0000f, 16.5000f, 18, 22}, // 043a + {0.283203f, 0.906738f, 0.292480f, 0.917480f, -1.6250f, -22.0000f, 16.5000f, 19, 22}, // 043b + {0.604980f, 0.425293f, 0.615723f, 0.436035f, 0.1250f, -22.0000f, 22.1875f, 22, 22}, // 043c + {0.978027f, 0.916016f, 0.986328f, 0.926758f, -0.0625f, -22.0000f, 16.7500f, 17, 22}, // 043d + {0.648926f, 0.729492f, 0.658203f, 0.740723f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 043e + {0.112793f, 0.916504f, 0.121094f, 0.927246f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 043f + {0.009766f, 0.873047f, 0.018555f, 0.887695f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0440 + {0.931152f, 0.915527f, 0.939453f, 0.926758f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0441 + {0.335938f, 0.912598f, 0.344727f, 0.923340f, -1.0625f, -21.9375f, 15.3125f, 18, 22}, // 0442 + {0.452637f, 0.857422f, 0.461914f, 0.872070f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0443 + {0.153320f, 0.051758f, 0.166992f, 0.069824f, -0.7500f, -29.8750f, 26.0625f, 28, 37}, // 0444 + {0.549316f, 0.912598f, 0.558105f, 0.923340f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0445 + {0.859375f, 0.197266f, 0.868652f, 0.210938f, -0.0625f, -22.0000f, 17.8125f, 19, 28}, // 0446 + {0.129883f, 0.916504f, 0.138184f, 0.927246f, -0.1875f, -22.0000f, 16.4375f, 17, 22}, // 0447 + {0.126465f, 0.863770f, 0.138672f, 0.874512f, -0.0625f, -22.0000f, 24.0625f, 25, 22}, // 0448 + {0.122070f, 0.762207f, 0.135254f, 0.775391f, -0.0625f, -22.0000f, 25.7500f, 27, 27}, // 0449 + {0.682617f, 0.471191f, 0.693359f, 0.481934f, -1.5000f, -22.0000f, 18.6875f, 22, 22}, // 044a + {0.960449f, 0.852539f, 0.973145f, 0.863281f, 0.5000f, -22.0000f, 23.8750f, 26, 22}, // 044b + {0.558594f, 0.913086f, 0.567383f, 0.923828f, 0.1250f, -22.0000f, 16.3125f, 18, 22}, // 044c + {0.016113f, 0.916016f, 0.024414f, 0.927246f, -0.6875f, -22.2500f, 15.6250f, 17, 23}, // 044d + {0.356934f, 0.562500f, 0.369629f, 0.573730f, 0.1875f, -22.2500f, 24.0000f, 26, 23}, // 044e + {0.637695f, 0.913086f, 0.646484f, 0.923828f, -0.9375f, -22.0000f, 16.7500f, 18, 22}, // 044f + {0.927246f, 0.861328f, 0.936035f, 0.876465f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 0450 + {0.960449f, 0.876953f, 0.969238f, 0.891113f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 0451 + {0.881836f, 0.741699f, 0.891602f, 0.760254f, -2.7500f, -29.9375f, 16.6875f, 20, 38}, // 0452 + {0.364746f, 0.902832f, 0.372070f, 0.917480f, -0.0625f, -29.3125f, 12.4375f, 15, 30}, // 0453 + {0.121094f, 0.916016f, 0.129395f, 0.927246f, -0.7500f, -22.2500f, 15.6875f, 17, 23}, // 0454 + {0.247559f, 0.916016f, 0.255859f, 0.927246f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0455 + {0.979980f, 0.292969f, 0.983887f, 0.307617f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0456 + {0.657227f, 0.903809f, 0.664551f, 0.917969f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 0457 + {0.183594f, 0.903320f, 0.188965f, 0.921875f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 0458 + {0.629395f, 0.221191f, 0.643066f, 0.231934f, -1.3125f, -22.0000f, 25.5000f, 28, 22}, // 0459 + {0.386719f, 0.588379f, 0.399902f, 0.599121f, -0.0625f, -22.0000f, 25.5625f, 27, 22}, // 045a + {0.010254f, 0.857910f, 0.019531f, 0.872559f, -1.8750f, -29.9375f, 16.8125f, 19, 30}, // 045b + {0.266602f, 0.873047f, 0.275391f, 0.887695f, 0.1250f, -29.2500f, 16.5000f, 18, 30}, // 045c + {0.355469f, 0.886230f, 0.363770f, 0.900879f, -0.0625f, -29.3750f, 16.8125f, 17, 30}, // 045d + {0.404785f, 0.806152f, 0.414063f, 0.824219f, -1.6875f, -29.4375f, 15.0000f, 19, 37}, // 045e + {0.730469f, 0.058594f, 0.738770f, 0.072266f, -0.0625f, -22.0000f, 16.8125f, 17, 28}, // 045f + {0.521973f, 0.689941f, 0.536133f, 0.704102f, -0.3750f, -28.5000f, 28.0625f, 29, 29}, // 0460 + {0.336914f, 0.328125f, 0.348633f, 0.338867f, -1.5000f, -22.0000f, 20.6875f, 24, 22}, // 0461 + {0.545410f, 0.830078f, 0.556152f, 0.844238f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 0462 + {0.170410f, 0.843750f, 0.180176f, 0.858398f, -2.1875f, -30.0000f, 16.3125f, 20, 30}, // 0463 + {0.916992f, 0.356445f, 0.930176f, 0.370605f, 0.6250f, -28.5625f, 26.3750f, 27, 29}, // 0464 + {0.311035f, 0.547363f, 0.322754f, 0.558594f, 0.1250f, -22.2500f, 22.1250f, 24, 23}, // 0465 + {0.710938f, 0.818848f, 0.722168f, 0.833008f, -1.5000f, -28.1875f, 18.5625f, 23, 29}, // 0466 + {0.665527f, 0.124512f, 0.675293f, 0.135254f, -1.7500f, -22.0000f, 16.1875f, 20, 22}, // 0467 + {0.014648f, 0.690430f, 0.028809f, 0.704590f, 0.9375f, -28.1875f, 26.8125f, 29, 29}, // 0468 + {0.200195f, 0.863770f, 0.212402f, 0.874512f, 0.7500f, -22.0000f, 23.0000f, 25, 22}, // 0469 + {0.347656f, 0.750488f, 0.360352f, 0.764648f, 0.0000f, -28.1250f, 25.3750f, 26, 29}, // 046a + {0.969727f, 0.891602f, 0.980469f, 0.902344f, -0.0625f, -22.0000f, 21.6250f, 22, 22}, // 046b + {0.113281f, 0.199219f, 0.130371f, 0.213379f, 0.5625f, -28.1250f, 33.6250f, 35, 29}, // 046c + {0.048340f, 0.820313f, 0.062988f, 0.831055f, 0.1875f, -22.0000f, 29.1875f, 30, 22}, // 046d + {0.682129f, 0.752930f, 0.690430f, 0.773926f, -1.2500f, -35.6250f, 15.3125f, 17, 43}, // 046e + {0.886230f, 0.831543f, 0.894531f, 0.849609f, -1.1250f, -29.8750f, 14.6250f, 17, 37}, // 046f + {0.722656f, 0.818848f, 0.733887f, 0.833008f, -0.8125f, -28.1875f, 20.9375f, 23, 29}, // 0470 + {0.900391f, 0.814941f, 0.911621f, 0.829590f, -0.7500f, -22.0000f, 21.3125f, 23, 30}, // 0471 + {0.086914f, 0.838379f, 0.097168f, 0.852539f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 0472 + {0.932617f, 0.903809f, 0.941895f, 0.915039f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 0473 + {0.269531f, 0.819336f, 0.280762f, 0.833496f, -1.6875f, -28.5625f, 18.8125f, 23, 29}, // 0474 + {0.450684f, 0.904297f, 0.459961f, 0.915527f, -1.5000f, -22.2500f, 15.0000f, 19, 23}, // 0475 + {0.548340f, 0.721680f, 0.559570f, 0.738770f, -1.6875f, -34.9375f, 18.8125f, 23, 35}, // 0476 + {0.599609f, 0.833984f, 0.609375f, 0.849121f, -2.2500f, -30.1250f, 15.0000f, 20, 31}, // 0477 + {0.977051f, 0.000000f, 0.995605f, 0.017578f, -0.3750f, -28.5625f, 35.1875f, 38, 36}, // 0478 + {0.927246f, 0.051270f, 0.944336f, 0.065918f, -0.7500f, -22.3125f, 31.7500f, 35, 30}, // 0479 + {0.384766f, 0.813965f, 0.395020f, 0.830078f, -0.3750f, -30.3750f, 20.2500f, 21, 33}, // 047a + {0.849121f, 0.652344f, 0.858398f, 0.665527f, -0.7500f, -24.0625f, 16.7500f, 19, 27}, // 047b + {0.709473f, 0.019531f, 0.723633f, 0.038086f, -0.3750f, -37.2500f, 28.0625f, 29, 38}, // 047c + {0.222656f, 0.705078f, 0.235352f, 0.720703f, -0.4375f, -31.3125f, 24.0625f, 26, 32}, // 047d + {0.340332f, 0.192383f, 0.354492f, 0.209473f, -0.3750f, -33.7500f, 28.0625f, 29, 35}, // 047e + {0.775391f, 0.813965f, 0.787109f, 0.828125f, -1.5000f, -28.5625f, 20.6875f, 24, 29}, // 047f + {0.534180f, 0.808105f, 0.543945f, 0.825195f, -0.3750f, -28.5625f, 18.8125f, 20, 35}, // 0480 + {0.045898f, 0.891602f, 0.054199f, 0.905762f, -0.5625f, -22.3125f, 15.8125f, 17, 29}, // 0481 + {0.456055f, 0.070801f, 0.465820f, 0.083984f, -0.3125f, -26.3125f, 18.4375f, 20, 27}, // 0482 + {0.771973f, 0.150879f, 0.779297f, 0.155762f, 0.1250f, -29.4375f, 14.5625f, 15, 10}, // 0483 + {0.320801f, 0.321289f, 0.328125f, 0.325684f, 0.4375f, -29.8750f, 15.2500f, 15, 9}, // 0484 + {0.398438f, 0.301270f, 0.402344f, 0.306152f, 0.6250f, -31.1250f, 8.6875f, 8, 10}, // 0485 + {0.617676f, 0.378418f, 0.621582f, 0.383301f, 0.6875f, -31.1250f, 9.1875f, 8, 10}, // 0486 + {0.135742f, 0.762207f, 0.148926f, 0.775391f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0487 + {0.810059f, 0.020996f, 0.825684f, 0.037598f, -1.0625f, -28.1875f, 29.7500f, 32, 34}, // 0488 + {0.955566f, 0.018555f, 0.970703f, 0.036133f, -0.8125f, -28.5625f, 28.8125f, 31, 36}, // 0489 + {0.987305f, 0.228516f, 0.999023f, 0.248535f, 0.2500f, -35.1250f, 20.7500f, 24, 41}, // 048a + {0.824219f, 0.810547f, 0.833984f, 0.827637f, -0.0625f, -29.4375f, 16.7500f, 20, 35}, // 048b + {0.683594f, 0.830078f, 0.694336f, 0.844238f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 048c + {0.746094f, 0.155273f, 0.755859f, 0.166016f, -2.4375f, -22.0000f, 16.3125f, 20, 22}, // 048d + {0.745605f, 0.850586f, 0.755371f, 0.864746f, 0.1875f, -28.1875f, 18.6250f, 20, 29}, // 048e + {0.498047f, 0.873047f, 0.506836f, 0.887695f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 048f + {0.208008f, 0.831543f, 0.216797f, 0.848633f, 0.2500f, -34.1250f, 16.3750f, 18, 35}, // 0490 + {0.882813f, 0.634766f, 0.890137f, 0.648438f, -0.0625f, -27.4375f, 13.5000f, 15, 28}, // 0491 + {0.809082f, 0.850586f, 0.818848f, 0.864746f, -2.0625f, -28.1250f, 16.3750f, 20, 29}, // 0492 + {0.155762f, 0.916504f, 0.164063f, 0.927246f, -2.3125f, -22.0000f, 12.4375f, 17, 22}, // 0493 + {0.857422f, 0.850586f, 0.867188f, 0.864746f, 0.2500f, -28.1875f, 17.1250f, 20, 29}, // 0494 + {0.833008f, 0.496094f, 0.841797f, 0.509277f, -0.0625f, -22.0000f, 16.3125f, 18, 27}, // 0495 + {0.407715f, 0.022461f, 0.422852f, 0.039551f, -1.6875f, -28.1875f, 25.5625f, 31, 35}, // 0496 + {0.263184f, 0.745605f, 0.276367f, 0.759277f, -1.6250f, -22.0000f, 22.6875f, 27, 28}, // 0497 + {0.754395f, 0.745117f, 0.764648f, 0.762695f, -0.3750f, -28.5000f, 19.6875f, 21, 36}, // 0498 + {0.523926f, 0.873047f, 0.532715f, 0.887695f, -0.5000f, -22.2500f, 16.2500f, 18, 30}, // 0499 + {0.852051f, 0.739746f, 0.862793f, 0.756836f, 0.3125f, -28.1875f, 18.8125f, 22, 35}, // 049a + {0.842285f, 0.260254f, 0.851563f, 0.273926f, 0.1250f, -22.0000f, 16.5000f, 19, 28}, // 049b + {0.846680f, 0.838379f, 0.856934f, 0.852539f, 0.2500f, -28.1875f, 19.0625f, 21, 29}, // 049c + {0.498047f, 0.906738f, 0.507324f, 0.917480f, 0.1250f, -22.0000f, 16.6250f, 19, 22}, // 049d + {0.174805f, 0.814453f, 0.186523f, 0.828613f, -2.8125f, -28.1875f, 18.8125f, 24, 29}, // 049e + {0.891602f, 0.213379f, 0.901855f, 0.228027f, -2.9375f, -29.9375f, 15.5000f, 21, 30}, // 049f + {0.223633f, 0.690430f, 0.237793f, 0.704590f, -0.7500f, -28.1875f, 25.1875f, 29, 29}, // 04a0 + {0.326172f, 0.853027f, 0.338867f, 0.863770f, -1.0000f, -21.9375f, 21.5625f, 26, 22}, // 04a1 + {0.042969f, 0.722168f, 0.054199f, 0.739258f, 0.3125f, -28.1875f, 20.8125f, 23, 35}, // 04a2 + {0.697754f, 0.139160f, 0.707520f, 0.152832f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04a3 + {0.962891f, 0.666504f, 0.977539f, 0.680664f, 0.3125f, -28.1875f, 28.8750f, 30, 29}, // 04a4 + {0.980957f, 0.891602f, 0.991699f, 0.902344f, -0.0625f, -22.0000f, 21.0000f, 22, 22}, // 04a5 + {0.680176f, 0.632324f, 0.695313f, 0.646484f, 0.2500f, -28.1875f, 30.1875f, 31, 29}, // 04a6 + {0.468750f, 0.196777f, 0.483398f, 0.209473f, -0.0625f, -22.0000f, 25.6250f, 30, 26}, // 04a7 + {0.787109f, 0.830078f, 0.797852f, 0.844238f, -0.3750f, -28.4375f, 20.6875f, 22, 29}, // 04a8 + {0.731934f, 0.904785f, 0.741211f, 0.916016f, -0.7500f, -22.1875f, 16.8750f, 19, 23}, // 04a9 + {0.742188f, 0.805176f, 0.751953f, 0.822754f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 04aa + {0.037109f, 0.886719f, 0.045410f, 0.901367f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 04ab + {0.177246f, 0.761230f, 0.187500f, 0.778320f, -1.3750f, -28.1875f, 17.3125f, 21, 35}, // 04ac + {0.898438f, 0.572754f, 0.907227f, 0.586426f, -1.0625f, -22.0000f, 15.3125f, 18, 28}, // 04ad + {0.900391f, 0.830078f, 0.911133f, 0.844238f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 04ae + {0.052734f, 0.863281f, 0.062012f, 0.877441f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04af + {0.381348f, 0.830566f, 0.392090f, 0.844727f, -1.5625f, -28.1875f, 18.7500f, 22, 29}, // 04b0 + {0.151367f, 0.863281f, 0.160645f, 0.877441f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04b1 + {0.336426f, 0.740723f, 0.347168f, 0.757813f, -1.2500f, -28.1875f, 18.6875f, 22, 35}, // 04b2 + {0.937500f, 0.308594f, 0.946777f, 0.322266f, -1.4375f, -22.0000f, 15.0000f, 19, 28}, // 04b3 + {0.623047f, 0.017578f, 0.638672f, 0.034668f, -1.2500f, -28.1875f, 26.3750f, 32, 35}, // 04b4 + {0.496094f, 0.825195f, 0.507324f, 0.838867f, -1.3125f, -22.0000f, 20.4375f, 23, 28}, // 04b5 + {0.156738f, 0.722168f, 0.167969f, 0.739258f, 0.1875f, -28.1875f, 20.3125f, 23, 35}, // 04b6 + {0.989746f, 0.777344f, 0.999512f, 0.791016f, -0.1875f, -22.0000f, 16.5000f, 20, 28}, // 04b7 + {0.916992f, 0.850586f, 0.926758f, 0.864746f, 0.1875f, -28.1875f, 20.1250f, 20, 29}, // 04b8 + {0.171387f, 0.916504f, 0.179688f, 0.927246f, -0.1875f, -22.0000f, 16.5000f, 17, 22}, // 04b9 + {0.217773f, 0.851074f, 0.227539f, 0.865234f, 2.6875f, -28.1875f, 20.3750f, 20, 29}, // 04ba + {0.195801f, 0.916504f, 0.204102f, 0.927246f, 2.3125f, -22.0625f, 16.5625f, 17, 22}, // 04bb + {0.484863f, 0.750488f, 0.497559f, 0.764648f, -1.5625f, -28.5000f, 24.6250f, 26, 29}, // 04bc + {0.730469f, 0.219727f, 0.740723f, 0.230957f, -2.5625f, -22.2500f, 17.6250f, 21, 23}, // 04bd + {0.582031f, 0.504395f, 0.594727f, 0.521973f, -1.5625f, -28.5000f, 24.6250f, 26, 36}, // 04be + {0.872559f, 0.649414f, 0.882813f, 0.664063f, -2.5625f, -22.3125f, 17.6250f, 21, 30}, // 04bf + {0.562012f, 0.503418f, 0.565918f, 0.517578f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04c0 + {0.138672f, 0.051758f, 0.152832f, 0.069336f, -1.6875f, -35.1250f, 25.6250f, 29, 36}, // 04c1 + {0.082031f, 0.732422f, 0.094727f, 0.747070f, -1.6250f, -29.4375f, 22.6875f, 26, 30}, // 04c2 + {0.911621f, 0.833984f, 0.921387f, 0.849121f, 0.2500f, -28.1875f, 18.6875f, 20, 31}, // 04c3 + {0.693359f, 0.891602f, 0.702148f, 0.904785f, 0.1250f, -22.0000f, 16.5000f, 18, 27}, // 04c4 + {0.885254f, 0.664063f, 0.897461f, 0.680664f, -1.2500f, -28.1875f, 20.8125f, 25, 34}, // 04c5 + {0.000000f, 0.834961f, 0.010742f, 0.848633f, -1.6250f, -22.0000f, 16.5000f, 22, 28}, // 04c6 + {0.276855f, 0.745605f, 0.287109f, 0.763184f, 0.2500f, -28.1875f, 20.8125f, 21, 36}, // 04c7 + {0.666016f, 0.886719f, 0.674316f, 0.901367f, -0.0625f, -22.0000f, 16.7500f, 17, 30}, // 04c8 + {0.727539f, 0.703125f, 0.739258f, 0.719727f, 0.3125f, -28.1875f, 20.8125f, 24, 34}, // 04c9 + {0.768066f, 0.858398f, 0.777832f, 0.872070f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04ca + {0.198242f, 0.811035f, 0.208008f, 0.828125f, 0.1875f, -28.1875f, 20.3125f, 20, 35}, // 04cb + {0.806641f, 0.604492f, 0.814941f, 0.618164f, -0.1875f, -22.0000f, 16.4375f, 17, 28}, // 04cc + {0.000000f, 0.503906f, 0.013672f, 0.520508f, 0.1875f, -28.1875f, 24.8125f, 28, 34}, // 04cd + {0.740723f, 0.026367f, 0.752930f, 0.040039f, 0.1250f, -22.0000f, 22.1875f, 25, 28}, // 04ce + {0.184082f, 0.504395f, 0.187988f, 0.518555f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04cf + {0.669434f, 0.724609f, 0.680176f, 0.742188f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 04d0 + {0.029297f, 0.861816f, 0.038086f, 0.876953f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 04d1 + {0.670898f, 0.752930f, 0.681641f, 0.769531f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 04d2 + {0.027832f, 0.877441f, 0.036621f, 0.891602f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 04d3 + {0.000000f, 0.632813f, 0.015137f, 0.646973f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 04d4 + {0.450684f, 0.291504f, 0.463867f, 0.302734f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 04d5 + {0.459473f, 0.824707f, 0.468262f, 0.842285f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 04d6 + {0.436035f, 0.861816f, 0.444824f, 0.876953f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 04d7 + {0.444824f, 0.830566f, 0.455566f, 0.844727f, -0.6250f, -28.5000f, 21.1875f, 22, 29}, // 04d8 + {0.477051f, 0.908691f, 0.485840f, 0.919922f, 2.2500f, -22.3750f, 15.7500f, 18, 23}, // 04d9 + {0.395508f, 0.755859f, 0.406250f, 0.772461f, -0.6250f, -33.1250f, 21.1875f, 22, 34}, // 04da + {0.867676f, 0.863281f, 0.876953f, 0.877441f, 0.8750f, -28.6250f, 15.7500f, 19, 29}, // 04db + {0.801758f, 0.371582f, 0.815918f, 0.388184f, -1.6875f, -33.9375f, 25.6250f, 29, 34}, // 04dc + {0.570313f, 0.750488f, 0.583008f, 0.764648f, -1.6250f, -28.2500f, 22.6875f, 26, 29}, // 04dd + {0.223633f, 0.761230f, 0.233887f, 0.778320f, -0.3750f, -34.2500f, 19.6875f, 21, 35}, // 04de + {0.062500f, 0.877441f, 0.071289f, 0.891602f, -0.5000f, -28.5625f, 16.2500f, 18, 29}, // 04df + {0.973633f, 0.863281f, 0.982910f, 0.877441f, -0.5000f, -28.1250f, 17.1875f, 19, 29}, // 04e0 + {0.983398f, 0.863281f, 0.992676f, 0.877441f, -0.5000f, -22.0000f, 17.1875f, 19, 29}, // 04e1 + {0.676270f, 0.805664f, 0.686523f, 0.822266f, 0.2500f, -33.6250f, 20.7500f, 21, 34}, // 04e2 + {0.741699f, 0.893555f, 0.750000f, 0.907227f, -0.0625f, -27.9375f, 16.8125f, 17, 28}, // 04e3 + {0.813477f, 0.805664f, 0.823730f, 0.822266f, 0.2500f, -33.9375f, 20.7500f, 21, 34}, // 04e4 + {0.146484f, 0.891602f, 0.154785f, 0.905762f, -0.0625f, -28.2500f, 16.8125f, 17, 29}, // 04e5 + {0.234375f, 0.761230f, 0.244629f, 0.778320f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 04e6 + {0.000000f, 0.863770f, 0.009277f, 0.877930f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 04e7 + {0.432617f, 0.838867f, 0.442871f, 0.853027f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 04e8 + {0.873535f, 0.905273f, 0.882813f, 0.916504f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 04e9 + {0.406738f, 0.761230f, 0.416992f, 0.778320f, -0.3750f, -33.8125f, 20.2500f, 21, 35}, // 04ea + {0.273438f, 0.857910f, 0.282715f, 0.872559f, -0.7500f, -29.0000f, 16.7500f, 19, 30}, // 04eb + {0.282715f, 0.811035f, 0.292480f, 0.828125f, 0.0000f, -34.3125f, 19.2500f, 20, 35}, // 04ec + {0.166016f, 0.891602f, 0.174316f, 0.905762f, -0.6875f, -28.5625f, 15.6250f, 17, 29}, // 04ed + {0.191895f, 0.756348f, 0.202637f, 0.772949f, -1.3125f, -33.6250f, 18.8750f, 22, 34}, // 04ee + {0.617188f, 0.815430f, 0.626465f, 0.833008f, -1.6875f, -28.0000f, 15.0000f, 19, 36}, // 04ef + {0.648926f, 0.740723f, 0.659668f, 0.757813f, -1.3125f, -33.9375f, 18.9375f, 22, 35}, // 04f0 + {0.626953f, 0.815430f, 0.636230f, 0.833008f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 04f1 + {0.840820f, 0.724609f, 0.851563f, 0.742188f, -1.3125f, -35.0000f, 18.8750f, 22, 36}, // 04f2 + {0.460938f, 0.806152f, 0.470215f, 0.824219f, -1.6875f, -29.3750f, 15.0000f, 19, 37}, // 04f3 + {0.115723f, 0.816895f, 0.125488f, 0.833496f, 0.1875f, -33.9375f, 20.3125f, 20, 34}, // 04f4 + {0.234863f, 0.891602f, 0.243164f, 0.905762f, -0.1875f, -28.2500f, 16.4375f, 17, 29}, // 04f5 + {0.217285f, 0.831543f, 0.226074f, 0.848633f, 0.1875f, -28.1875f, 16.3125f, 18, 35}, // 04f6 + {0.569824f, 0.906250f, 0.577148f, 0.919922f, -0.0625f, -22.0000f, 12.4375f, 15, 28}, // 04f7 + {0.108887f, 0.503906f, 0.122559f, 0.520508f, 0.2500f, -33.9375f, 25.3750f, 28, 34}, // 04f8 + {0.892090f, 0.750488f, 0.904785f, 0.764648f, 0.5000f, -28.2500f, 23.8750f, 26, 29}, // 04f9 + {0.051270f, 0.746094f, 0.061523f, 0.763672f, -1.1250f, -28.1875f, 17.6250f, 21, 36}, // 04fa + {0.674805f, 0.886719f, 0.683105f, 0.901367f, -1.1875f, -22.0000f, 12.3750f, 17, 30}, // 04fb + {0.973145f, 0.699219f, 0.984375f, 0.716797f, -1.2500f, -28.1875f, 18.7500f, 23, 36}, // 04fc + {0.822266f, 0.844238f, 0.832031f, 0.858887f, -1.4375f, -22.0000f, 15.0000f, 20, 30}, // 04fd + {0.953613f, 0.830566f, 0.964355f, 0.844727f, -1.3125f, -28.1875f, 18.6875f, 22, 29}, // 04fe + {0.665039f, 0.913086f, 0.673828f, 0.923828f, -1.4375f, -22.0000f, 15.0625f, 18, 22}, // 04ff +// RANGE: 0x2121 - 0x2123, start 0x260 + {0.722656f, 0.867188f, 0.739258f, 0.875000f, 1.0000f, -23.5000f, 35.1875f, 34, 16}, // 2121 + {0.586426f, 0.180664f, 0.595703f, 0.187012f, -0.5000f, -28.1875f, 18.5625f, 19, 13}, // 2122 +// RANGE: 0xfffd - 0xfffe, start 0x262 + {0.902344f, 0.000000f, 0.917969f, 0.023926f, -0.6250f, -39.6875f, 30.1875f, 32, 49}, // fffd +// RANGE: 0x180 - 0x251, start 0x263 + {0.433105f, 0.370605f, 0.442871f, 0.383301f, -2.4375f, -25.4375f, 16.6875f, 20, 26}, // 0180 + {0.713379f, 0.690430f, 0.725586f, 0.703125f, -2.0000f, -25.4375f, 22.1875f, 25, 26}, // 0181 + {0.237305f, 0.863770f, 0.247559f, 0.876465f, 0.3750f, -25.4375f, 19.6250f, 21, 26}, // 0182 + {0.833008f, 0.894531f, 0.841797f, 0.907227f, -0.0625f, -25.4375f, 16.6875f, 18, 26}, // 0183 + {0.413574f, 0.895020f, 0.422363f, 0.907715f, 0.0000f, -25.4375f, 16.6875f, 18, 26}, // 0184 + {0.460449f, 0.895020f, 0.469238f, 0.907715f, 0.0000f, -25.5000f, 16.6875f, 18, 26}, // 0185 + {0.682129f, 0.203613f, 0.693359f, 0.216797f, -0.8750f, -25.8125f, 21.6875f, 23, 27}, // 0186 + {0.561035f, 0.806152f, 0.573730f, 0.819336f, -0.5000f, -26.4375f, 22.9375f, 26, 27}, // 0187 + {0.650879f, 0.188965f, 0.661133f, 0.199707f, -0.8125f, -21.0000f, 17.3750f, 21, 22}, // 0188 + {0.162598f, 0.821777f, 0.174805f, 0.834473f, -1.9375f, -25.4375f, 21.6875f, 25, 26}, // 0189 + {0.661621f, 0.235352f, 0.674805f, 0.248047f, -2.0000f, -25.4375f, 23.6875f, 27, 26}, // 018a + {0.960449f, 0.863770f, 0.970703f, 0.876465f, -0.9375f, -25.4375f, 19.6250f, 21, 26}, // 018b + {0.214355f, 0.895508f, 0.223145f, 0.908203f, -0.7500f, -25.4375f, 16.6875f, 18, 26}, // 018c + {0.009766f, 0.888184f, 0.019043f, 0.900879f, -0.9375f, -19.8750f, 16.7500f, 19, 26}, // 018d + {0.821289f, 0.542480f, 0.831055f, 0.555176f, -0.3750f, -25.4375f, 20.0000f, 20, 26}, // 018e + {0.723145f, 0.833496f, 0.734375f, 0.846680f, -0.6875f, -25.8125f, 21.9375f, 23, 27}, // 018f + {0.520508f, 0.083984f, 0.530273f, 0.097168f, -0.7500f, -25.8125f, 18.1250f, 20, 27}, // 0190 + {0.064453f, 0.816406f, 0.075195f, 0.831543f, -2.6875f, -25.4375f, 18.3125f, 22, 31}, // 0191 + {0.898926f, 0.308105f, 0.905762f, 0.323242f, -2.4375f, -25.8125f, 8.3750f, 14, 31}, // 0192 + {0.555664f, 0.762207f, 0.568848f, 0.775391f, -0.4375f, -26.4375f, 23.7500f, 27, 27}, // 0193 + {0.914063f, 0.740723f, 0.925781f, 0.756348f, -2.0000f, -25.4375f, 19.5000f, 24, 32}, // 0194 + {0.985840f, 0.577637f, 0.998535f, 0.590332f, 0.0000f, -25.4375f, 24.1875f, 26, 26}, // 0195 + {0.445801f, 0.307129f, 0.450684f, 0.319824f, 0.0000f, -25.4375f, 7.3125f, 10, 26}, // 0196 + {0.674805f, 0.219727f, 0.681641f, 0.232422f, -2.0000f, -25.4375f, 9.6250f, 14, 26}, // 0197 + {0.948730f, 0.762207f, 0.959961f, 0.774902f, 0.1875f, -25.5625f, 20.0000f, 23, 26}, // 0198 + {0.531738f, 0.902832f, 0.540039f, 0.915527f, 0.0000f, -25.8125f, 15.0000f, 17, 26}, // 0199 + {0.834961f, 0.276367f, 0.841797f, 0.289063f, -2.0000f, -25.4375f, 9.6250f, 14, 26}, // 019a + {0.266113f, 0.888184f, 0.275391f, 0.900879f, -1.6250f, -25.4375f, 15.0000f, 19, 26}, // 019b + {0.125977f, 0.816895f, 0.138672f, 0.829590f, -0.0625f, -25.4375f, 25.0000f, 26, 26}, // 019c + {0.039063f, 0.757324f, 0.050781f, 0.772461f, -2.6875f, -25.4375f, 21.6875f, 24, 31}, // 019d + {0.540527f, 0.902832f, 0.548828f, 0.915527f, 0.0625f, -19.8750f, 16.7500f, 17, 26}, // 019e + {0.953613f, 0.816895f, 0.965820f, 0.830078f, -0.6250f, -25.8125f, 23.3125f, 25, 27}, // 019f + {0.853516f, 0.324219f, 0.866211f, 0.337891f, -0.6250f, -27.0000f, 23.2500f, 26, 28}, // 01a0 + {0.407715f, 0.056152f, 0.417480f, 0.067383f, -0.9375f, -22.1875f, 16.6875f, 20, 23}, // 01a1 + {0.242676f, 0.028809f, 0.258301f, 0.041992f, -0.6250f, -25.8125f, 30.5625f, 32, 27}, // 01a2 + {0.483398f, 0.817383f, 0.495605f, 0.830566f, -0.9375f, -19.8750f, 23.4375f, 25, 27}, // 01a3 + {0.763184f, 0.822266f, 0.775391f, 0.834961f, -2.0000f, -25.4375f, 22.0625f, 25, 26}, // 01a4 + {0.533203f, 0.873047f, 0.541992f, 0.887695f, 0.0625f, -23.1250f, 16.6875f, 18, 30}, // 01a5 + {0.752441f, 0.805176f, 0.764160f, 0.819824f, 0.3750f, -25.4375f, 21.6875f, 24, 30}, // 01a6 + {0.380371f, 0.845215f, 0.391113f, 0.858398f, -0.4375f, -25.8125f, 20.0000f, 22, 27}, // 01a7 + {0.283691f, 0.917969f, 0.291992f, 0.928223f, -0.8125f, -19.8750f, 15.0625f, 17, 21}, // 01a8 + {0.318848f, 0.877441f, 0.328613f, 0.890137f, -0.6250f, -25.4375f, 18.0625f, 20, 26}, // 01a9 + {0.516113f, 0.887695f, 0.523926f, 0.902832f, -1.0000f, -26.0000f, 10.9375f, 16, 31}, // 01aa + {0.759277f, 0.763184f, 0.765137f, 0.777832f, -1.5000f, -25.0625f, 8.3125f, 12, 30}, // 01ab + {0.431641f, 0.877441f, 0.441406f, 0.890137f, -1.3125f, -25.4375f, 17.1250f, 20, 26}, // 01ac + {0.537598f, 0.051758f, 0.543457f, 0.064453f, -1.5000f, -25.4375f, 8.3125f, 12, 26}, // 01ad + {0.199707f, 0.061523f, 0.209961f, 0.077148f, -1.3125f, -25.4375f, 18.3750f, 21, 32}, // 01ae + {0.635254f, 0.438965f, 0.647461f, 0.452637f, 0.3750f, -27.0000f, 23.2500f, 25, 28}, // 01af + {0.054688f, 0.892090f, 0.064941f, 0.903320f, 0.0000f, -22.5625f, 18.6250f, 21, 23}, // 01b0 + {0.531738f, 0.844727f, 0.542969f, 0.857422f, 0.0000f, -25.4375f, 22.4375f, 23, 26}, // 01b1 + {0.543457f, 0.844727f, 0.554688f, 0.857422f, -1.8750f, -25.8125f, 20.0000f, 23, 26}, // 01b2 + {0.256348f, 0.816895f, 0.269043f, 0.829590f, -1.0625f, -25.8125f, 22.5000f, 26, 26}, // 01b3 + {0.520020f, 0.834473f, 0.531250f, 0.847656f, -1.5625f, -19.8125f, 18.4375f, 23, 27}, // 01b4 + {0.062500f, 0.864258f, 0.072754f, 0.876953f, -1.4375f, -25.4375f, 18.3750f, 21, 26}, // 01b5 + {0.585449f, 0.916992f, 0.594238f, 0.926758f, -1.3750f, -19.5625f, 15.0000f, 18, 20}, // 01b6 + {0.298828f, 0.864258f, 0.309082f, 0.876953f, -0.8125f, -25.4375f, 18.8125f, 21, 26}, // 01b7 + {0.323242f, 0.864258f, 0.333496f, 0.876953f, -0.6250f, -25.4375f, 18.8125f, 21, 26}, // 01b8 + {0.480469f, 0.895508f, 0.489258f, 0.908203f, -0.7500f, -19.5625f, 15.8125f, 18, 26}, // 01b9 + {0.813477f, 0.902832f, 0.821777f, 0.915527f, -0.9375f, -19.5625f, 14.4375f, 17, 26}, // 01ba + {0.377441f, 0.888184f, 0.386719f, 0.900879f, -1.0625f, -25.8125f, 16.7500f, 19, 26}, // 01bb + {0.593262f, 0.877441f, 0.603027f, 0.890137f, -1.6250f, -25.4375f, 16.6250f, 20, 26}, // 01bc + {0.646973f, 0.916992f, 0.655762f, 0.926758f, -0.8750f, -19.5000f, 15.7500f, 18, 20}, // 01bd + {0.853027f, 0.895508f, 0.861816f, 0.908203f, -0.6875f, -25.4375f, 16.6250f, 18, 26}, // 01be + {0.822266f, 0.902832f, 0.830566f, 0.915527f, 0.0625f, -19.8750f, 16.6875f, 17, 26}, // 01bf + {0.957520f, 0.068848f, 0.960938f, 0.081543f, 0.7500f, -25.4375f, 8.3750f, 7, 26}, // 01c0 + {0.747070f, 0.731445f, 0.753418f, 0.744141f, 0.7500f, -25.4375f, 13.8750f, 13, 26}, // 01c1 + {0.969727f, 0.902832f, 0.978027f, 0.915527f, -1.2500f, -25.4375f, 14.2500f, 17, 26}, // 01c2 + {0.899902f, 0.100586f, 0.903320f, 0.113281f, 0.6875f, -25.4375f, 8.3750f, 7, 26}, // 01c3 + {0.839355f, 0.015137f, 0.859375f, 0.030273f, 0.3750f, -30.8750f, 40.0000f, 41, 31}, // 01c4 + {0.933594f, 0.371582f, 0.952148f, 0.384277f, 0.3750f, -25.8125f, 36.6250f, 38, 26}, // 01c5 + {0.257813f, 0.603516f, 0.274414f, 0.616699f, -0.9375f, -25.8750f, 31.6875f, 34, 27}, // 01c6 + {0.517578f, 0.720215f, 0.532715f, 0.732910f, 0.2500f, -25.4375f, 30.8750f, 31, 26}, // 01c7 + {0.644043f, 0.758301f, 0.655273f, 0.773926f, 0.2500f, -25.5000f, 23.3125f, 23, 32}, // 01c8 + {0.610352f, 0.817871f, 0.617188f, 0.833496f, 0.0000f, -25.4375f, 13.3125f, 14, 32}, // 01c9 + {0.123047f, 0.505859f, 0.140625f, 0.518555f, 0.3750f, -25.4375f, 36.6250f, 36, 26}, // 01ca + {0.985840f, 0.164551f, 0.999512f, 0.180176f, 0.3750f, -25.4375f, 28.3125f, 28, 32}, // 01cb + {0.926270f, 0.740723f, 0.937988f, 0.756348f, 0.0625f, -25.5000f, 23.3750f, 24, 32}, // 01cc + {0.691406f, 0.734375f, 0.703613f, 0.749512f, -2.0625f, -30.9375f, 20.0000f, 25, 31}, // 01cd + {0.191895f, 0.743164f, 0.201172f, 0.756348f, -0.8750f, -25.8125f, 16.6875f, 19, 27}, // 01ce + {0.992676f, 0.668457f, 0.999512f, 0.683594f, -2.5625f, -31.0000f, 8.3750f, 14, 31}, // 01cf + {0.930664f, 0.324707f, 0.937500f, 0.337402f, -2.5625f, -25.8125f, 8.3125f, 14, 26}, // 01d0 + {0.666504f, 0.455566f, 0.678711f, 0.471191f, -0.6250f, -31.0000f, 23.3125f, 25, 32}, // 01d1 + {0.203125f, 0.756348f, 0.212402f, 0.769531f, -0.9375f, -25.8750f, 16.6875f, 19, 27}, // 01d2 + {0.296387f, 0.096191f, 0.306641f, 0.111816f, 0.3750f, -31.0000f, 21.6250f, 21, 32}, // 01d3 + {0.894043f, 0.513672f, 0.902344f, 0.526855f, 0.0000f, -25.8125f, 16.6875f, 17, 27}, // 01d4 + {0.417480f, 0.761230f, 0.427734f, 0.778320f, 0.3750f, -34.0625f, 21.6250f, 21, 35}, // 01d5 + {0.776367f, 0.886719f, 0.784668f, 0.901367f, 0.0000f, -28.9375f, 16.6875f, 17, 30}, // 01d6 + {0.474121f, 0.734375f, 0.484375f, 0.752441f, 0.3750f, -36.0000f, 21.6250f, 21, 37}, // 01d7 + {0.991211f, 0.196777f, 0.999512f, 0.212402f, 0.0000f, -30.8750f, 16.6875f, 17, 32}, // 01d8 + {0.501953f, 0.734375f, 0.512207f, 0.752441f, 0.3750f, -36.0000f, 21.6250f, 21, 37}, // 01d9 + {0.864258f, 0.665527f, 0.872559f, 0.681152f, 0.0000f, -30.8750f, 16.6875f, 17, 32}, // 01da + {0.680664f, 0.734375f, 0.690918f, 0.752441f, 0.3750f, -36.0000f, 21.6250f, 21, 37}, // 01db + {0.546875f, 0.857910f, 0.555176f, 0.873535f, 0.0000f, -30.8750f, 16.6875f, 17, 32}, // 01dc + {0.921387f, 0.909180f, 0.930664f, 0.919434f, -0.8125f, -19.8750f, 16.6875f, 19, 21}, // 01dd + {0.897461f, 0.663574f, 0.909668f, 0.680664f, -2.0625f, -34.0625f, 20.0000f, 25, 35}, // 01de + {0.501953f, 0.857910f, 0.511230f, 0.872559f, -0.8750f, -28.9375f, 16.6875f, 19, 30}, // 01df + {0.481445f, 0.664063f, 0.493652f, 0.681152f, -2.0625f, -34.0625f, 20.0000f, 25, 35}, // 01e0 + {0.527344f, 0.857910f, 0.536621f, 0.872559f, -0.8750f, -28.9375f, 16.6875f, 19, 30}, // 01e1 + {0.334473f, 0.370605f, 0.350586f, 0.385254f, -2.0000f, -29.9375f, 30.0000f, 33, 30}, // 01e2 + {0.024414f, 0.750977f, 0.038574f, 0.763672f, -1.0000f, -24.8750f, 26.6250f, 29, 26}, // 01e3 + {0.876465f, 0.806152f, 0.889160f, 0.819336f, -0.4375f, -25.8125f, 23.3750f, 26, 27}, // 01e4 + {0.767090f, 0.715332f, 0.776855f, 0.728516f, -1.0000f, -19.8750f, 16.6875f, 20, 27}, // 01e5 + {0.805176f, 0.741211f, 0.816895f, 0.756836f, -0.4375f, -31.0000f, 23.3750f, 24, 32}, // 01e6 + {0.443359f, 0.845215f, 0.452148f, 0.861328f, -1.0000f, -25.8750f, 16.6250f, 18, 33}, // 01e7 + {0.104492f, 0.816895f, 0.115234f, 0.832031f, 0.1875f, -31.0000f, 20.0000f, 22, 31}, // 01e8 + {0.019043f, 0.875000f, 0.027344f, 0.890137f, 0.0000f, -31.0000f, 15.0000f, 17, 31}, // 01e9 + {0.461914f, 0.706055f, 0.474121f, 0.722168f, -0.6250f, -25.8125f, 23.3125f, 25, 33}, // 01ea + {0.942383f, 0.877441f, 0.951660f, 0.890625f, -1.0000f, -19.8750f, 16.6875f, 19, 27}, // 01eb + {0.986328f, 0.559082f, 0.998535f, 0.577148f, -0.6250f, -29.8750f, 23.3125f, 25, 37}, // 01ec + {0.905762f, 0.291992f, 0.915039f, 0.307617f, -1.0000f, -24.8750f, 16.6875f, 19, 32}, // 01ed + {0.951172f, 0.861816f, 0.959961f, 0.876953f, -0.5625f, -30.9375f, 16.0000f, 18, 31}, // 01ee + {0.097656f, 0.849121f, 0.106445f, 0.864746f, -0.5625f, -25.8125f, 16.0000f, 18, 32}, // 01ef + {0.524414f, 0.901367f, 0.531250f, 0.917480f, -3.5000f, -25.8750f, 6.6250f, 14, 33}, // 01f0 + {0.423340f, 0.022461f, 0.443359f, 0.035156f, 0.3750f, -25.4375f, 39.9375f, 41, 26}, // 01f1 + {0.952637f, 0.371582f, 0.971191f, 0.384277f, 0.3750f, -25.4375f, 36.6250f, 38, 26}, // 01f2 + {0.160645f, 0.663086f, 0.177246f, 0.675781f, -0.9375f, -25.4375f, 31.6875f, 34, 26}, // 01f3 + {0.291504f, 0.741699f, 0.303223f, 0.757324f, -0.4375f, -31.0000f, 23.3750f, 24, 32}, // 01f4 + {0.951172f, 0.845215f, 0.959961f, 0.861328f, -1.0000f, -25.8750f, 16.6250f, 18, 33}, // 01f5 + {0.704590f, 0.762207f, 0.717773f, 0.775391f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 01f6 + {0.811523f, 0.762207f, 0.824707f, 0.775391f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 01f7 + {0.509277f, 0.762695f, 0.522461f, 0.775879f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 01f8 + {0.594238f, 0.762695f, 0.607422f, 0.775879f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 01f9 + {0.781250f, 0.603516f, 0.793457f, 0.621094f, -2.0625f, -35.2500f, 19.9375f, 25, 36}, // 01fa + {0.941406f, 0.831543f, 0.950684f, 0.847656f, -0.8750f, -32.0625f, 16.6875f, 19, 33}, // 01fb + {0.193359f, 0.189941f, 0.209473f, 0.205078f, -2.0000f, -30.9375f, 30.0000f, 33, 31}, // 01fc + {0.886719f, 0.728027f, 0.900879f, 0.741211f, -1.0000f, -25.8125f, 26.6250f, 29, 27}, // 01fd + {0.692383f, 0.705078f, 0.705078f, 0.720703f, -0.8125f, -30.9375f, 23.3125f, 26, 32}, // 01fe + {0.781738f, 0.728516f, 0.791016f, 0.742188f, -0.1250f, -25.8750f, 18.3125f, 19, 28}, // 01ff + {0.168457f, 0.734863f, 0.180664f, 0.750000f, -2.0625f, -30.7500f, 20.0000f, 25, 31}, // 0200 + {0.050293f, 0.877930f, 0.059570f, 0.891113f, -0.8750f, -25.8125f, 16.6875f, 19, 27}, // 0201 + {0.353516f, 0.734863f, 0.365723f, 0.750000f, -2.0625f, -30.5625f, 20.0000f, 25, 31}, // 0202 + {0.491211f, 0.888184f, 0.500488f, 0.900879f, -0.8750f, -25.6250f, 16.6875f, 19, 26}, // 0203 + {0.346680f, 0.820313f, 0.356934f, 0.835449f, 0.3750f, -30.8125f, 20.0000f, 21, 31}, // 0204 + {0.146484f, 0.877930f, 0.155762f, 0.891113f, -0.8125f, -25.8125f, 16.7500f, 19, 27}, // 0205 + {0.752441f, 0.820313f, 0.762695f, 0.835449f, 0.3750f, -30.6250f, 20.0000f, 21, 31}, // 0206 + {0.524414f, 0.888184f, 0.533691f, 0.900879f, -0.8125f, -25.6250f, 16.7500f, 19, 26}, // 0207 + {0.715332f, 0.895508f, 0.722656f, 0.910645f, -3.6875f, -30.8125f, 8.3750f, 15, 31}, // 0208 + {0.530273f, 0.067871f, 0.537598f, 0.080566f, -3.6250f, -25.8125f, 8.3125f, 15, 26}, // 0209 + {0.292969f, 0.908203f, 0.299316f, 0.923340f, -2.1250f, -30.6250f, 8.3750f, 13, 31}, // 020a + {0.611328f, 0.749023f, 0.617676f, 0.761719f, -2.2500f, -25.6250f, 8.3125f, 13, 26}, // 020b + {0.250488f, 0.722168f, 0.262695f, 0.737793f, -0.6250f, -30.8125f, 23.3125f, 25, 32}, // 020c + {0.170410f, 0.877930f, 0.179688f, 0.891113f, -0.9375f, -25.8125f, 16.6875f, 19, 27}, // 020d + {0.484863f, 0.734863f, 0.497070f, 0.750000f, -0.6250f, -30.6250f, 23.3125f, 25, 31}, // 020e + {0.785156f, 0.888184f, 0.794434f, 0.900879f, -0.9375f, -25.6250f, 16.6875f, 19, 26}, // 020f + {0.495605f, 0.392578f, 0.506836f, 0.407715f, 0.3750f, -30.7500f, 21.6875f, 23, 31}, // 0210 + {0.224609f, 0.093262f, 0.231934f, 0.105957f, -1.6250f, -25.8125f, 10.0000f, 15, 26}, // 0211 + {0.163086f, 0.806152f, 0.174316f, 0.821289f, 0.3750f, -30.5625f, 21.6875f, 23, 31}, // 0212 + {0.604492f, 0.657715f, 0.611328f, 0.670410f, -0.8750f, -25.6250f, 10.0000f, 14, 26}, // 0213 + {0.151855f, 0.817871f, 0.162109f, 0.833496f, 0.3750f, -30.8125f, 21.6250f, 21, 32}, // 0214 + {0.785156f, 0.901367f, 0.793457f, 0.914551f, 0.0000f, -25.8125f, 16.6875f, 17, 27}, // 0215 + {0.921387f, 0.820313f, 0.931641f, 0.835449f, 0.3750f, -30.6250f, 21.6250f, 21, 31}, // 0216 + {0.978516f, 0.902832f, 0.986816f, 0.915527f, 0.0000f, -25.6250f, 16.6875f, 17, 26}, // 0217 + {0.607910f, 0.762695f, 0.621094f, 0.775879f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0218 + {0.621582f, 0.762695f, 0.634766f, 0.775879f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0219 + {0.718262f, 0.762695f, 0.731445f, 0.775879f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021a + {0.010742f, 0.763184f, 0.023926f, 0.776367f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021b + {0.088867f, 0.763184f, 0.102051f, 0.776367f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021c + {0.313965f, 0.763184f, 0.327148f, 0.776367f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021d + {0.731934f, 0.763184f, 0.745117f, 0.776367f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021e + {0.745605f, 0.763184f, 0.758789f, 0.776367f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 021f + {0.271973f, 0.763672f, 0.285156f, 0.776855f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0220 + {0.024414f, 0.764160f, 0.037598f, 0.777344f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0221 + {0.102539f, 0.764160f, 0.115723f, 0.777344f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0222 + {0.690918f, 0.764648f, 0.704102f, 0.777832f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0223 + {0.161133f, 0.765137f, 0.174316f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0224 + {0.338379f, 0.765137f, 0.351563f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0225 + {0.428223f, 0.765137f, 0.441406f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0226 + {0.479004f, 0.765137f, 0.492188f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0227 + {0.569336f, 0.765137f, 0.582520f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0228 + {0.887207f, 0.765137f, 0.900391f, 0.778320f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0229 + {0.051270f, 0.765625f, 0.064453f, 0.778809f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022a + {0.245117f, 0.765625f, 0.258301f, 0.778809f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022b + {0.352051f, 0.765625f, 0.365234f, 0.778809f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022c + {0.365723f, 0.765625f, 0.378906f, 0.778809f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022d + {0.379395f, 0.765625f, 0.392578f, 0.778809f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022e + {0.441895f, 0.766113f, 0.455078f, 0.779297f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 022f + {0.859863f, 0.766113f, 0.873047f, 0.779297f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0230 + {0.541992f, 0.767090f, 0.555176f, 0.780273f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0231 + {0.838867f, 0.769531f, 0.852051f, 0.782715f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0232 + {0.203125f, 0.770020f, 0.216309f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0233 + {0.285645f, 0.770020f, 0.298828f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0234 + {0.455566f, 0.770020f, 0.468750f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0235 + {0.492676f, 0.770020f, 0.505859f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0236 + {0.522949f, 0.770020f, 0.536133f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0237 + {0.666504f, 0.770020f, 0.679688f, 0.783203f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0238 + {0.038086f, 0.772949f, 0.051270f, 0.786133f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0239 + {0.393066f, 0.772949f, 0.406250f, 0.786133f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023a + {0.797363f, 0.772949f, 0.810547f, 0.786133f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023b + {0.187988f, 0.773438f, 0.201172f, 0.786621f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023c + {0.900879f, 0.773926f, 0.914063f, 0.787109f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023d + {0.914551f, 0.773926f, 0.927734f, 0.787109f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023e + {0.635254f, 0.774414f, 0.648438f, 0.787598f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 023f + {0.948730f, 0.774902f, 0.961914f, 0.788086f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0240 + {0.064941f, 0.775391f, 0.078125f, 0.788574f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0241 + {0.116211f, 0.775879f, 0.129395f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0242 + {0.129883f, 0.775879f, 0.143066f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0243 + {0.143555f, 0.775879f, 0.156738f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0244 + {0.258789f, 0.775879f, 0.271973f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0245 + {0.555664f, 0.775879f, 0.568848f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0246 + {0.704590f, 0.775879f, 0.717773f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0247 + {0.811035f, 0.775879f, 0.824219f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0248 + {0.962402f, 0.775879f, 0.975586f, 0.789063f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0249 + {0.506348f, 0.776367f, 0.519531f, 0.789551f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024a + {0.594238f, 0.776367f, 0.607422f, 0.789551f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024b + {0.607910f, 0.776367f, 0.621094f, 0.789551f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024c + {0.621582f, 0.776367f, 0.634766f, 0.789551f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024d + {0.718262f, 0.776367f, 0.731445f, 0.789551f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024e + {0.010742f, 0.776855f, 0.023926f, 0.790039f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 024f + {0.089355f, 0.909668f, 0.098633f, 0.919922f, -0.8125f, -19.8750f, 16.6875f, 19, 21}, // 0250 +// RANGE: 0x370 - 0x400, start 0x334 + {0.078613f, 0.776855f, 0.091797f, 0.790039f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0370 + {0.313965f, 0.776855f, 0.327148f, 0.790039f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0371 + {0.731934f, 0.776855f, 0.745117f, 0.790039f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0372 + {0.745605f, 0.776855f, 0.758789f, 0.790039f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0373 + {0.272949f, 0.106445f, 0.279297f, 0.112305f, -1.1250f, -25.4375f, 9.2500f, 13, 12}, // 0374 + {0.834473f, 0.129395f, 0.840820f, 0.135254f, -1.1250f, -7.6250f, 9.2500f, 13, 12}, // 0375 + {0.272461f, 0.777344f, 0.285645f, 0.790527f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0376 + {0.976074f, 0.777344f, 0.989258f, 0.790527f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0377 + {0.024414f, 0.777832f, 0.037598f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0378 + {0.092285f, 0.777832f, 0.105469f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0379 + {0.517578f, 0.407715f, 0.522461f, 0.412109f, 0.3750f, -2.7500f, 8.3125f, 10, 9}, // 037a + {0.299316f, 0.777832f, 0.312500f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037b + {0.759277f, 0.777832f, 0.772461f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037c + {0.772949f, 0.777832f, 0.786133f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037d + {0.866699f, 0.137207f, 0.870605f, 0.148926f, 0.5000f, -19.5000f, 8.3125f, 8, 24}, // 037e + {0.928223f, 0.777832f, 0.941406f, 0.791016f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 037f + {0.648926f, 0.778320f, 0.662109f, 0.791504f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0380 + {0.680176f, 0.778320f, 0.693359f, 0.791504f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0381 + {0.824707f, 0.778320f, 0.837891f, 0.791504f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0382 + {0.873535f, 0.778320f, 0.886719f, 0.791504f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0383 + {0.695801f, 0.423340f, 0.699707f, 0.427734f, 0.6250f, -26.0625f, 8.3125f, 8, 9}, // 0384 + {0.780273f, 0.288574f, 0.787109f, 0.292969f, -2.8125f, -26.0625f, 8.3125f, 14, 9}, // 0385 + {0.981934f, 0.817383f, 0.994141f, 0.830566f, -2.0625f, -26.0000f, 20.0000f, 25, 27}, // 0386 + {0.803223f, 0.070313f, 0.806641f, 0.073730f, 0.6875f, -16.0625f, 8.3750f, 7, 7}, // 0387 + {0.139160f, 0.817871f, 0.151367f, 0.831055f, -3.3125f, -26.0625f, 21.1250f, 25, 27}, // 0388 + {0.051270f, 0.806641f, 0.063965f, 0.819824f, -3.3125f, -26.0625f, 22.7500f, 26, 27}, // 0389 + {0.805664f, 0.713867f, 0.812012f, 0.727051f, -3.3125f, -26.0625f, 9.5000f, 13, 27}, // 038a + {0.157227f, 0.778809f, 0.170410f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 038b + {0.170898f, 0.778809f, 0.184082f, 0.791992f, -2.2500f, -26.0625f, 23.3125f, 27, 27}, // 038c + {0.216797f, 0.778809f, 0.229980f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 038d + {0.821289f, 0.308105f, 0.834961f, 0.321289f, -3.3125f, -26.0625f, 22.4375f, 28, 27}, // 038e + {0.243164f, 0.806641f, 0.255859f, 0.819824f, -2.1875f, -26.0625f, 22.7500f, 26, 27}, // 038f + {0.434082f, 0.151367f, 0.440918f, 0.164551f, -3.6875f, -26.0625f, 6.6875f, 14, 27}, // 0390 + {0.646484f, 0.822754f, 0.658691f, 0.835449f, -2.0625f, -25.4375f, 20.0000f, 25, 26}, // 0391 + {0.596191f, 0.864258f, 0.606445f, 0.876953f, 0.2500f, -25.4375f, 20.0625f, 21, 26}, // 0392 + {0.089355f, 0.896484f, 0.098145f, 0.909180f, 0.4375f, -25.4375f, 16.5000f, 18, 26}, // 0393 + {0.670898f, 0.822754f, 0.683105f, 0.835449f, -1.8750f, -25.4375f, 20.4375f, 25, 26}, // 0394 + {0.901367f, 0.864258f, 0.911621f, 0.876953f, 0.3750f, -25.4375f, 20.0000f, 21, 26}, // 0395 + {0.175781f, 0.864746f, 0.186035f, 0.877441f, -1.4375f, -25.4375f, 18.3750f, 21, 26}, // 0396 + {0.626465f, 0.864746f, 0.636719f, 0.877441f, 0.3750f, -25.4375f, 21.6250f, 21, 26}, // 0397 + {0.208496f, 0.817871f, 0.220703f, 0.831055f, -0.6250f, -25.8125f, 23.3125f, 25, 27}, // 0398 + {0.932129f, 0.117188f, 0.935547f, 0.129883f, 0.7500f, -25.4375f, 8.3750f, 7, 26}, // 0399 + {0.000000f, 0.777832f, 0.010742f, 0.790527f, 0.1875f, -25.4375f, 20.0000f, 22, 26}, // 039a + {0.507813f, 0.833496f, 0.519531f, 0.846191f, -1.8750f, -25.4375f, 20.0000f, 24, 26}, // 039b + {0.811523f, 0.822754f, 0.823730f, 0.835449f, 0.3125f, -25.4375f, 25.0625f, 25, 26}, // 039c + {0.877441f, 0.864746f, 0.887695f, 0.877441f, 0.3750f, -25.4375f, 21.6875f, 21, 26}, // 039d + {0.662109f, 0.865234f, 0.672363f, 0.877930f, -0.3750f, -25.4375f, 19.5000f, 21, 26}, // 039e + {0.221191f, 0.817871f, 0.233398f, 0.831055f, -0.6250f, -25.8125f, 23.3125f, 25, 27}, // 039f + {0.745117f, 0.865234f, 0.755371f, 0.877930f, 0.3750f, -25.4375f, 21.6250f, 21, 26}, // 03a0 + {0.806152f, 0.865234f, 0.816406f, 0.877930f, 0.3125f, -25.4375f, 20.0000f, 21, 26}, // 03a1 + {0.230469f, 0.778809f, 0.243652f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03a2 + {0.683105f, 0.877441f, 0.692871f, 0.890137f, -0.6250f, -25.4375f, 18.0625f, 20, 26}, // 03a3 + {0.854004f, 0.865234f, 0.864258f, 0.877930f, -1.3125f, -25.4375f, 18.3750f, 21, 26}, // 03a4 + {0.610352f, 0.833496f, 0.622070f, 0.846191f, -1.8750f, -25.4375f, 20.0625f, 24, 26}, // 03a5 + {0.335938f, 0.806641f, 0.348633f, 0.819824f, -0.6250f, -26.1250f, 24.2500f, 26, 27}, // 03a6 + {0.622559f, 0.833496f, 0.634277f, 0.846191f, -1.9375f, -25.4375f, 20.0000f, 24, 26}, // 03a7 + {0.544434f, 0.816895f, 0.557129f, 0.829590f, -0.6250f, -25.4375f, 24.0625f, 26, 26}, // 03a8 + {0.710938f, 0.833496f, 0.722656f, 0.846191f, -0.4375f, -25.8125f, 22.7500f, 24, 26}, // 03a9 + {0.993164f, 0.863281f, 0.999512f, 0.877930f, -1.9375f, -29.7500f, 8.3125f, 13, 30}, // 03aa + {0.920898f, 0.805176f, 0.932617f, 0.819824f, -1.9375f, -29.7500f, 20.0000f, 24, 30}, // 03ab + {0.672852f, 0.873047f, 0.682617f, 0.886230f, -0.9375f, -26.0625f, 17.3125f, 20, 27}, // 03ac + {0.909668f, 0.526855f, 0.917480f, 0.540039f, -1.1250f, -26.0625f, 13.0625f, 16, 27}, // 03ad + {0.097168f, 0.865234f, 0.105469f, 0.880859f, 0.0625f, -26.0625f, 16.7500f, 17, 32}, // 03ae + {0.473145f, 0.038574f, 0.477051f, 0.051758f, 0.0000f, -26.0625f, 6.6250f, 8, 27}, // 03af + {0.036133f, 0.901855f, 0.044434f, 0.915039f, 0.0625f, -26.0625f, 16.5625f, 17, 27}, // 03b0 + {0.796875f, 0.622559f, 0.806641f, 0.632813f, -0.9375f, -19.8750f, 17.3125f, 20, 21}, // 03b1 + {0.078125f, 0.849609f, 0.086914f, 0.865234f, 0.0000f, -25.8125f, 16.9375f, 18, 32}, // 03b2 + {0.156250f, 0.889648f, 0.165527f, 0.902344f, -1.6250f, -19.5000f, 15.0000f, 19, 26}, // 03b3 + {0.195801f, 0.889648f, 0.205078f, 0.902344f, -0.9375f, -25.4375f, 16.7500f, 19, 26}, // 03b4 + {0.424805f, 0.842773f, 0.432617f, 0.853027f, -1.1250f, -19.8750f, 13.0625f, 16, 21}, // 03b5 + {0.952148f, 0.877441f, 0.959961f, 0.893066f, -0.9375f, -25.4375f, 13.1875f, 16, 32}, // 03b6 + {0.174805f, 0.903320f, 0.183105f, 0.916016f, 0.0625f, -19.8750f, 16.7500f, 17, 26}, // 03b7 + {0.865234f, 0.891602f, 0.874023f, 0.904785f, -0.6250f, -25.8125f, 16.7500f, 18, 27}, // 03b8 + {0.787109f, 0.058594f, 0.790527f, 0.068359f, 0.0000f, -19.5000f, 6.6250f, 7, 20}, // 03b9 + {0.674316f, 0.916992f, 0.683105f, 0.926758f, -0.0625f, -19.5000f, 14.9375f, 18, 20}, // 03ba + {0.364258f, 0.889648f, 0.373535f, 0.902344f, -1.6250f, -25.4375f, 15.0000f, 19, 26}, // 03bb + {0.515137f, 0.903320f, 0.523438f, 0.916016f, 0.0000f, -19.5000f, 16.6250f, 17, 26}, // 03bc + {0.064941f, 0.765625f, 0.074219f, 0.775391f, -1.6250f, -19.5625f, 15.0000f, 19, 20}, // 03bd + {0.787598f, 0.871582f, 0.795410f, 0.887695f, -0.9375f, -25.8125f, 13.0000f, 16, 33}, // 03be + {0.431641f, 0.910156f, 0.440918f, 0.920410f, -0.9375f, -19.8750f, 16.6875f, 19, 21}, // 03bf + {0.252441f, 0.892090f, 0.264160f, 0.901855f, -1.5000f, -19.5625f, 20.3750f, 24, 20}, // 03c0 + {0.470703f, 0.889648f, 0.479980f, 0.902344f, 0.0000f, -19.8750f, 17.1875f, 19, 26}, // 03c1 + {0.883789f, 0.901855f, 0.892090f, 0.915039f, -0.9375f, -19.8750f, 14.1875f, 17, 27}, // 03c2 + {0.702637f, 0.903809f, 0.712891f, 0.914063f, -0.9375f, -20.0625f, 18.6250f, 21, 21}, // 03c3 + {0.594727f, 0.090332f, 0.602051f, 0.100098f, -1.5000f, -19.5625f, 11.5000f, 15, 20}, // 03c4 + {0.079590f, 0.918457f, 0.087891f, 0.928223f, 0.0625f, -19.5000f, 16.5625f, 17, 20}, // 03c5 + {0.641113f, 0.853027f, 0.651855f, 0.865723f, -0.9375f, -19.8750f, 19.5000f, 22, 26}, // 03c6 + {0.705566f, 0.877441f, 0.715332f, 0.890137f, -1.8125f, -19.5000f, 15.6875f, 20, 26}, // 03c7 + {0.842773f, 0.853027f, 0.853516f, 0.865723f, 0.0000f, -19.5000f, 21.8750f, 22, 26}, // 03c8 + {0.111816f, 0.059570f, 0.124023f, 0.069336f, -0.9375f, -19.5000f, 23.0000f, 25, 20}, // 03c9 + {0.375977f, 0.752930f, 0.382324f, 0.765625f, -2.7500f, -25.3125f, 6.6875f, 13, 26}, // 03ca + {0.723145f, 0.903320f, 0.731445f, 0.916016f, 0.0625f, -25.3125f, 16.5625f, 17, 26}, // 03cb + {0.243652f, 0.877930f, 0.252930f, 0.891113f, -0.9375f, -26.0625f, 16.6875f, 19, 27}, // 03cc + {0.124023f, 0.902344f, 0.132324f, 0.915527f, 0.0625f, -26.0625f, 16.5625f, 17, 27}, // 03cd + {0.574219f, 0.817871f, 0.586426f, 0.831055f, -0.9375f, -26.0625f, 23.0000f, 25, 27}, // 03ce + {0.327637f, 0.778809f, 0.340820f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03cf + {0.874512f, 0.891602f, 0.883301f, 0.904785f, 0.0000f, -25.8125f, 16.9375f, 18, 27}, // 03d0 + {0.479492f, 0.845703f, 0.490234f, 0.858887f, -1.3125f, -25.8125f, 18.5000f, 22, 27}, // 03d1 + {0.681641f, 0.844727f, 0.692871f, 0.857422f, -1.8750f, -25.5625f, 18.8750f, 23, 26}, // 03d2 + {0.406738f, 0.778809f, 0.419922f, 0.791992f, -3.3125f, -26.0625f, 21.7500f, 27, 27}, // 03d3 + {0.447754f, 0.815430f, 0.458984f, 0.830078f, -1.8750f, -29.8125f, 18.9375f, 23, 30}, // 03d4 + {0.416504f, 0.354980f, 0.427246f, 0.370605f, -0.9375f, -25.4375f, 19.3125f, 22, 32}, // 03d5 + {0.826172f, 0.020996f, 0.838867f, 0.030762f, -1.4375f, -19.5000f, 23.4375f, 26, 20}, // 03d6 + {0.420410f, 0.778809f, 0.433594f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d7 + {0.469238f, 0.778809f, 0.482422f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d8 + {0.569336f, 0.778809f, 0.582520f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03d9 + {0.988281f, 0.148438f, 0.999512f, 0.164551f, -0.5000f, -25.8125f, 21.6250f, 23, 33}, // 03da + {0.887207f, 0.778809f, 0.900391f, 0.791992f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03db + {0.228027f, 0.851074f, 0.236816f, 0.866699f, 0.3750f, -25.4375f, 17.3125f, 18, 32}, // 03dc + {0.051758f, 0.779297f, 0.064941f, 0.792480f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03dd + {0.057617f, 0.832031f, 0.066895f, 0.848145f, -0.6250f, -25.8125f, 17.1250f, 19, 33}, // 03de + {0.244141f, 0.779297f, 0.257324f, 0.792480f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03df + {0.158691f, 0.834961f, 0.169922f, 0.848145f, -1.3125f, -25.8125f, 20.7500f, 23, 27}, // 03e0 + {0.341309f, 0.779297f, 0.354492f, 0.792480f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03e1 + {0.173828f, 0.705566f, 0.186523f, 0.721191f, 0.3750f, -25.4375f, 26.3125f, 26, 32}, // 03e2 + {0.687012f, 0.816895f, 0.699707f, 0.829590f, -0.1250f, -19.5625f, 25.0000f, 26, 26}, // 03e3 + {0.912109f, 0.865234f, 0.922363f, 0.877930f, -0.2500f, -25.6250f, 20.5000f, 21, 26}, // 03e4 + {0.223633f, 0.897461f, 0.232422f, 0.910156f, -0.6250f, -19.6250f, 16.7500f, 18, 26}, // 03e5 + {0.599609f, 0.817871f, 0.609863f, 0.833496f, 0.3750f, -25.4375f, 20.3750f, 21, 32}, // 03e6 + {0.911621f, 0.905273f, 0.920898f, 0.916504f, -1.2500f, -21.6875f, 15.8750f, 19, 23}, // 03e7 + {0.916504f, 0.891602f, 0.925293f, 0.904785f, -0.6250f, -25.8125f, 16.6875f, 18, 27}, // 03e8 + {0.054688f, 0.903809f, 0.062988f, 0.916504f, -0.5625f, -19.8750f, 15.1250f, 17, 26}, // 03e9 + {0.785156f, 0.844727f, 0.796387f, 0.857422f, -1.9375f, -25.4375f, 18.6875f, 23, 26}, // 03ea + {0.862305f, 0.905273f, 0.873047f, 0.915039f, -1.5625f, -19.8750f, 18.0625f, 22, 20}, // 03eb + {0.231934f, 0.077148f, 0.242188f, 0.090332f, -0.1250f, -26.4375f, 18.3125f, 21, 27}, // 03ec + {0.665039f, 0.901855f, 0.675293f, 0.912598f, -0.9375f, -21.2500f, 18.3125f, 21, 22}, // 03ed + {0.897461f, 0.877441f, 0.907227f, 0.890137f, -1.4375f, -25.4375f, 17.0000f, 20, 26}, // 03ee + {0.804688f, 0.893555f, 0.812988f, 0.907227f, -1.6875f, -22.1250f, 12.9375f, 17, 28}, // 03ef + {0.892578f, 0.903809f, 0.902832f, 0.914063f, -1.4375f, -19.8750f, 17.9375f, 21, 21}, // 03f0 + {0.625488f, 0.877930f, 0.634766f, 0.891113f, 0.0000f, -19.8750f, 17.1875f, 19, 27}, // 03f1 + {0.531738f, 0.916016f, 0.540527f, 0.926270f, -0.8125f, -19.8750f, 15.0000f, 18, 21}, // 03f2 + {0.256348f, 0.916016f, 0.261230f, 0.931641f, -3.3750f, -25.5000f, 6.6250f, 10, 32}, // 03f3 + {0.354980f, 0.779297f, 0.368164f, 0.792480f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f4 + {0.368652f, 0.779297f, 0.381836f, 0.792480f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f5 + {0.434082f, 0.779785f, 0.447266f, 0.792969f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f6 + {0.852539f, 0.779785f, 0.865723f, 0.792969f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f7 + {0.536621f, 0.780762f, 0.549805f, 0.793945f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f8 + {0.838379f, 0.783203f, 0.851563f, 0.796387f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03f9 + {0.201660f, 0.783691f, 0.214844f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fa + {0.286133f, 0.783691f, 0.299316f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fb + {0.447754f, 0.783691f, 0.460938f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fc + {0.482910f, 0.783691f, 0.496094f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fd + {0.520020f, 0.783691f, 0.533203f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03fe + {0.662598f, 0.783691f, 0.675781f, 0.796875f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 03ff +// RANGE: 0x590 - 0x600, start 0x3c4 + {0.038086f, 0.786621f, 0.051270f, 0.799805f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 0590 + {0.511230f, 0.413086f, 0.516113f, 0.416992f, 0.8750f, -2.1250f, 10.8125f, 10, 8}, // 0591 + {0.645508f, 0.231934f, 0.651855f, 0.235352f, -0.8750f, -23.9375f, 10.8125f, 13, 7}, // 0592 + {0.328613f, 0.321289f, 0.333008f, 0.326660f, 1.3125f, -27.6875f, 10.8125f, 9, 11}, // 0593 + {0.935059f, 0.019531f, 0.937988f, 0.023926f, 2.3750f, -25.8750f, 10.8125f, 6, 9}, // 0594 + {0.541016f, 0.338379f, 0.545410f, 0.342773f, 1.1250f, -25.8750f, 10.8125f, 9, 9}, // 0595 + {0.995117f, 0.405762f, 0.999512f, 0.410156f, 1.0625f, -2.7500f, 10.8125f, 9, 9}, // 0596 + {0.803223f, 0.074219f, 0.806641f, 0.077637f, 1.9375f, -23.8750f, 10.8125f, 7, 7}, // 0597 + {0.595215f, 0.504395f, 0.600098f, 0.508301f, 0.4375f, -24.5625f, 10.8125f, 10, 8}, // 0598 + {0.995117f, 0.410645f, 0.999512f, 0.415039f, -2.0000f, -25.6250f, 10.8125f, 9, 9}, // 0599 + {0.695801f, 0.428223f, 0.699707f, 0.432617f, 4.8125f, -2.7500f, 10.8125f, 8, 9}, // 059a + {0.533203f, 0.416992f, 0.537598f, 0.421387f, 1.0625f, -2.7500f, 10.8125f, 9, 9}, // 059b + {0.757324f, 0.460938f, 0.761719f, 0.465332f, 1.0625f, -25.6250f, 10.8125f, 9, 9}, // 059c + {0.757324f, 0.465820f, 0.761719f, 0.470215f, 4.1875f, -25.6250f, 10.8125f, 9, 9}, // 059d + {0.553223f, 0.322754f, 0.559082f, 0.327637f, 1.1875f, -26.5000f, 10.8125f, 12, 10}, // 059e + {0.545410f, 0.322754f, 0.552734f, 0.327148f, -1.6875f, -25.5000f, 10.8125f, 15, 9}, // 059f + {0.772461f, 0.471191f, 0.776855f, 0.475586f, 4.0000f, -25.5000f, 10.8125f, 9, 9}, // 05a0 + {0.526855f, 0.416992f, 0.532715f, 0.421387f, -0.3125f, -25.5000f, 10.8125f, 12, 9}, // 05a1 + {0.382324f, 0.786621f, 0.395508f, 0.799805f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05a2 + {0.694336f, 0.501465f, 0.698242f, 0.505371f, 0.7500f, -2.1250f, 10.8125f, 8, 8}, // 05a3 + {0.502441f, 0.470215f, 0.506348f, 0.474609f, 1.5000f, -2.7500f, 10.8125f, 8, 9}, // 05a4 + {0.772461f, 0.476074f, 0.776855f, 0.480469f, 1.1250f, -2.7500f, 10.8125f, 9, 9}, // 05a5 + {0.511230f, 0.407715f, 0.517090f, 0.412598f, -0.3750f, -3.0000f, 10.8125f, 12, 10}, // 05a6 + {0.617676f, 0.383789f, 0.621582f, 0.388672f, 1.5000f, -3.0000f, 10.8125f, 8, 10}, // 05a7 + {0.698730f, 0.481934f, 0.703125f, 0.486328f, 1.1250f, -25.6250f, 10.8125f, 9, 9}, // 05a8 + {0.703613f, 0.481934f, 0.708008f, 0.486328f, -1.6875f, -25.5000f, 10.8125f, 9, 9}, // 05a9 + {0.595215f, 0.508789f, 0.600098f, 0.512695f, 0.8750f, -2.1250f, 10.8125f, 10, 8}, // 05aa + {0.518555f, 0.478027f, 0.522461f, 0.482422f, 1.5000f, -25.9375f, 10.8125f, 8, 9}, // 05ab + {0.277344f, 0.505859f, 0.281250f, 0.509766f, 0.7500f, -25.3125f, 10.8125f, 8, 8}, // 05ac + {0.802734f, 0.483887f, 0.807129f, 0.488281f, 4.1875f, -2.7500f, 10.8125f, 9, 9}, // 05ad + {0.577148f, 0.518066f, 0.582031f, 0.521973f, -2.0000f, -24.5625f, 10.8125f, 10, 8}, // 05ae + {0.709473f, 0.507324f, 0.713379f, 0.511230f, 1.7500f, -24.3750f, 10.8125f, 8, 8}, // 05af + {0.935059f, 0.024414f, 0.937988f, 0.028809f, 2.3750f, -2.5000f, 10.8125f, 6, 9}, // 05b0 + {0.032227f, 0.460938f, 0.038086f, 0.465332f, -0.4375f, -2.5000f, 10.8125f, 12, 9}, // 05b1 + {0.300293f, 0.479492f, 0.305664f, 0.483887f, 0.0625f, -2.5000f, 10.8125f, 11, 9}, // 05b2 + {0.306152f, 0.479492f, 0.311523f, 0.483887f, 0.0625f, -2.5000f, 10.8125f, 11, 9}, // 05b3 + {0.968262f, 0.036621f, 0.971191f, 0.039551f, 2.3750f, -2.5000f, 10.8125f, 6, 6}, // 05b4 + {0.433594f, 0.051758f, 0.437988f, 0.054688f, 1.0000f, -2.5000f, 10.8125f, 9, 6}, // 05b5 + {0.698730f, 0.486816f, 0.703125f, 0.491211f, 1.0000f, -2.5000f, 10.8125f, 9, 9}, // 05b6 + {0.439941f, 0.035645f, 0.443848f, 0.038574f, 1.5625f, -2.1875f, 10.8125f, 8, 6}, // 05b7 + {0.557617f, 0.208984f, 0.561523f, 0.212402f, 1.5625f, -2.1875f, 10.8125f, 8, 7}, // 05b8 + {0.968262f, 0.040039f, 0.971191f, 0.042969f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05b9 + {0.786621f, 0.786621f, 0.799805f, 0.799805f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ba + {0.038574f, 0.460938f, 0.044434f, 0.465332f, -0.4375f, -2.5000f, 10.8125f, 12, 9}, // 05bb + {0.968262f, 0.043457f, 0.971191f, 0.046387f, 2.3750f, -12.9375f, 10.8125f, 6, 6}, // 05bc + {0.935059f, 0.029297f, 0.937988f, 0.033203f, 2.7500f, -2.1250f, 10.8125f, 6, 8}, // 05bd + {0.698730f, 0.103027f, 0.705566f, 0.106445f, -1.3125f, -19.5625f, 11.0000f, 14, 7}, // 05be + {0.401855f, 0.148438f, 0.405762f, 0.151367f, 1.5625f, -22.6875f, 10.8125f, 8, 6}, // 05bf + {0.801270f, 0.343750f, 0.804688f, 0.355957f, 0.1250f, -21.9375f, 6.7500f, 7, 25}, // 05c0 + {0.968262f, 0.046875f, 0.971191f, 0.049805f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c1 + {0.851563f, 0.081055f, 0.854492f, 0.083984f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c2 + {0.562988f, 0.187012f, 0.566895f, 0.196777f, 0.0625f, -19.5625f, 7.1250f, 8, 20}, // 05c3 + {0.851563f, 0.084473f, 0.854492f, 0.087402f, 2.3750f, -23.0000f, 10.8125f, 6, 6}, // 05c4 + {0.184570f, 0.787109f, 0.197754f, 0.800293f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c5 + {0.900879f, 0.787598f, 0.914063f, 0.800781f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c6 + {0.914551f, 0.787598f, 0.927734f, 0.800781f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c7 + {0.635254f, 0.788086f, 0.648438f, 0.801270f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c8 + {0.941895f, 0.788574f, 0.955078f, 0.801758f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05c9 + {0.065430f, 0.789063f, 0.078613f, 0.802246f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ca + {0.105957f, 0.789551f, 0.119141f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cb + {0.119629f, 0.789551f, 0.132813f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cc + {0.133301f, 0.789551f, 0.146484f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cd + {0.257813f, 0.789551f, 0.270996f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ce + {0.550293f, 0.789551f, 0.563477f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05cf + {0.683594f, 0.916992f, 0.692383f, 0.926758f, -0.2500f, -19.5625f, 17.3125f, 18, 20}, // 05d0 + {0.354492f, 0.916016f, 0.363770f, 0.925781f, -0.8750f, -19.9375f, 16.8750f, 19, 20}, // 05d1 + {0.523926f, 0.917969f, 0.531738f, 0.927734f, -1.4375f, -19.9375f, 12.3125f, 16, 20}, // 05d2 + {0.871582f, 0.916992f, 0.880371f, 0.926758f, -1.3125f, -19.5625f, 15.3750f, 18, 20}, // 05d3 + {0.910156f, 0.916992f, 0.918945f, 0.926758f, 0.1250f, -19.9375f, 17.8125f, 18, 20}, // 05d4 + {0.417480f, 0.040039f, 0.423340f, 0.049805f, -1.5625f, -19.9375f, 9.5000f, 12, 20}, // 05d5 + {0.689453f, 0.076172f, 0.695801f, 0.086426f, -1.1875f, -20.3125f, 9.8125f, 13, 21}, // 05d6 + {0.957520f, 0.916992f, 0.966309f, 0.926758f, 0.1250f, -19.9375f, 17.8125f, 18, 20}, // 05d7 + {0.692383f, 0.916016f, 0.701172f, 0.926270f, 0.0000f, -19.9375f, 17.8125f, 18, 21}, // 05d8 + {0.363281f, 0.144043f, 0.369141f, 0.150391f, -1.5625f, -19.9375f, 9.5000f, 12, 13}, // 05d9 + {0.098633f, 0.903809f, 0.106934f, 0.916504f, -1.4375f, -19.9375f, 15.1875f, 17, 26}, // 05da + {0.299805f, 0.917969f, 0.308105f, 0.928223f, -0.8750f, -19.9375f, 15.8125f, 17, 21}, // 05db + {0.308105f, 0.903809f, 0.316406f, 0.916504f, -1.0625f, -25.5000f, 14.5000f, 17, 26}, // 05dc + {0.594727f, 0.917480f, 0.603516f, 0.927246f, 0.1250f, -19.5625f, 17.8125f, 18, 20}, // 05dd + {0.372559f, 0.916016f, 0.381836f, 0.925781f, -1.1250f, -19.9375f, 17.8125f, 19, 20}, // 05de + {0.892578f, 0.588379f, 0.898438f, 0.601074f, -1.5625f, -19.9375f, 9.5000f, 12, 26}, // 05df + {0.763184f, 0.123047f, 0.768555f, 0.132813f, -0.8750f, -19.9375f, 10.1250f, 11, 20}, // 05e0 + {0.670898f, 0.742676f, 0.680664f, 0.752930f, -1.2500f, -19.9375f, 18.1250f, 20, 21}, // 05e1 + {0.959473f, 0.905273f, 0.968750f, 0.916504f, -1.0625f, -19.5625f, 16.5000f, 19, 23}, // 05e2 + {0.794922f, 0.898926f, 0.803711f, 0.911621f, -0.6875f, -19.9375f, 17.0000f, 18, 26}, // 05e3 + {0.221191f, 0.910645f, 0.230469f, 0.920898f, -0.8750f, -19.9375f, 17.0625f, 19, 21}, // 05e4 + {0.422852f, 0.903809f, 0.431152f, 0.916504f, -0.9375f, -19.5625f, 15.1250f, 17, 26}, // 05e5 + {0.604004f, 0.917480f, 0.612793f, 0.927246f, -0.6875f, -19.5625f, 15.4375f, 18, 20}, // 05e6 + {0.074219f, 0.899414f, 0.083008f, 0.912109f, 0.1250f, -19.5625f, 17.5000f, 18, 26}, // 05e7 + {0.622559f, 0.918457f, 0.630859f, 0.928223f, -1.4375f, -19.9375f, 15.1875f, 17, 20}, // 05e8 + {0.769531f, 0.901855f, 0.780762f, 0.911621f, 0.1250f, -19.6250f, 21.0000f, 23, 20}, // 05e9 + {0.017090f, 0.905273f, 0.027344f, 0.915527f, -1.4375f, -19.9375f, 19.0000f, 21, 21}, // 05ea + {0.693848f, 0.789551f, 0.707031f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05eb + {0.800293f, 0.789551f, 0.813477f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ec + {0.955566f, 0.789551f, 0.968750f, 0.802734f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ed + {0.496582f, 0.790039f, 0.509766f, 0.803223f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ee + {0.583008f, 0.790039f, 0.596191f, 0.803223f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ef + {0.584961f, 0.106445f, 0.594727f, 0.116211f, -1.5625f, -19.9375f, 17.6875f, 20, 20}, // 05f0 + {0.570313f, 0.170898f, 0.580078f, 0.180664f, -1.5625f, -19.9375f, 17.6875f, 20, 20}, // 05f1 + {0.810547f, 0.177734f, 0.820313f, 0.184082f, -1.5625f, -19.9375f, 17.6875f, 20, 13}, // 05f2 + {0.492676f, 0.320313f, 0.497559f, 0.326172f, -0.6875f, -23.2500f, 6.5000f, 10, 12}, // 05f3 + {0.726074f, 0.278809f, 0.733887f, 0.284668f, -0.6875f, -23.2500f, 12.3750f, 16, 12}, // 05f4 + {0.596680f, 0.790039f, 0.609863f, 0.803223f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f5 + {0.610352f, 0.790039f, 0.623535f, 0.803223f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f6 + {0.707520f, 0.790039f, 0.720703f, 0.803223f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f7 + {0.000000f, 0.790527f, 0.013184f, 0.803711f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f8 + {0.079102f, 0.790527f, 0.092285f, 0.803711f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05f9 + {0.312988f, 0.790527f, 0.326172f, 0.803711f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fa + {0.721191f, 0.790527f, 0.734375f, 0.803711f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fb + {0.734863f, 0.790527f, 0.748047f, 0.803711f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fc + {0.271484f, 0.791016f, 0.284668f, 0.804199f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fd + {0.969238f, 0.791016f, 0.982422f, 0.804199f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05fe + {0.982910f, 0.791016f, 0.996094f, 0.804199f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 05ff +// RANGE: 0x1ea0 - 0x1efa, start 0x434 + {0.384766f, 0.722168f, 0.396973f, 0.737793f, -2.0625f, -25.4375f, 20.0000f, 25, 32}, // 1ea0 + {0.864746f, 0.877930f, 0.874023f, 0.891113f, -0.8750f, -19.8750f, 16.6875f, 19, 27}, // 1ea1 + {0.397461f, 0.722168f, 0.409668f, 0.737793f, -2.0625f, -31.9375f, 20.0000f, 25, 32}, // 1ea2 + {0.874512f, 0.877930f, 0.883789f, 0.891113f, -0.8750f, -26.6250f, 16.6875f, 19, 27}, // 1ea3 + {0.176270f, 0.688477f, 0.188477f, 0.705078f, -2.0625f, -33.3125f, 20.0000f, 25, 34}, // 1ea4 + {0.468750f, 0.838867f, 0.479004f, 0.853027f, -0.8750f, -28.2500f, 16.6875f, 21, 29}, // 1ea5 + {0.043945f, 0.688965f, 0.056152f, 0.705566f, -2.0625f, -33.3125f, 20.0000f, 25, 34}, // 1ea6 + {0.492188f, 0.839355f, 0.502441f, 0.853516f, -2.9375f, -28.2500f, 16.6875f, 21, 29}, // 1ea7 + {0.463379f, 0.688965f, 0.475586f, 0.705566f, -2.0625f, -33.8125f, 20.0000f, 25, 34}, // 1ea8 + {0.567383f, 0.831543f, 0.577637f, 0.846191f, -0.8750f, -28.7500f, 16.6875f, 21, 30}, // 1ea9 + {0.430664f, 0.604004f, 0.442871f, 0.621582f, -2.0625f, -35.6875f, 20.0000f, 25, 36}, // 1eaa + {0.619629f, 0.846680f, 0.628906f, 0.861816f, -0.8750f, -30.6250f, 16.6875f, 19, 31}, // 1eab + {0.987305f, 0.493652f, 0.999512f, 0.512207f, -2.0625f, -30.8750f, 20.0000f, 25, 38}, // 1eac + {0.097168f, 0.832520f, 0.106445f, 0.848633f, -0.8750f, -25.8750f, 16.6875f, 19, 33}, // 1ead + {0.443359f, 0.604004f, 0.455566f, 0.621582f, -2.0625f, -35.1250f, 20.0625f, 25, 36}, // 1eae + {0.707031f, 0.846680f, 0.716309f, 0.861816f, -0.8750f, -29.7500f, 16.6875f, 19, 31}, // 1eaf + {0.927734f, 0.604004f, 0.939941f, 0.621582f, -2.0625f, -35.1250f, 20.0625f, 25, 36}, // 1eb0 + {0.106934f, 0.847168f, 0.116211f, 0.862305f, -0.8750f, -29.7500f, 16.6875f, 19, 31}, // 1eb1 + {0.245117f, 0.603516f, 0.257324f, 0.621582f, -2.0625f, -36.1250f, 20.0625f, 25, 37}, // 1eb2 + {0.913086f, 0.586426f, 0.922363f, 0.602051f, -0.8750f, -30.8125f, 16.6875f, 19, 32}, // 1eb3 + {0.367188f, 0.604492f, 0.379395f, 0.622070f, -2.0625f, -35.7500f, 20.0000f, 25, 36}, // 1eb4 + {0.146484f, 0.847168f, 0.155762f, 0.862305f, -0.8750f, -30.3750f, 16.6875f, 19, 31}, // 1eb5 + {0.171387f, 0.504395f, 0.183594f, 0.522949f, -2.0625f, -31.0000f, 20.0625f, 25, 38}, // 1eb6 + {0.021973f, 0.843262f, 0.031250f, 0.858887f, -0.8750f, -25.6250f, 16.6875f, 19, 32}, // 1eb7 + {0.700195f, 0.817871f, 0.710449f, 0.833496f, 0.3750f, -25.4375f, 20.0000f, 21, 32}, // 1eb8 + {0.969727f, 0.877930f, 0.979004f, 0.891113f, -0.8125f, -19.8750f, 16.7500f, 19, 27}, // 1eb9 + {0.037598f, 0.818359f, 0.047852f, 0.833984f, 0.3750f, -32.0000f, 20.0000f, 21, 32}, // 1eba + {0.979492f, 0.877930f, 0.988770f, 0.891113f, -0.8125f, -26.6250f, 16.7500f, 19, 27}, // 1ebb + {0.800781f, 0.821289f, 0.811035f, 0.836426f, 0.3750f, -30.5000f, 20.0000f, 21, 31}, // 1ebc + {0.813477f, 0.889648f, 0.822754f, 0.902344f, -0.8125f, -25.4375f, 16.7500f, 19, 26}, // 1ebd + {0.905273f, 0.756836f, 0.916016f, 0.773438f, 0.3750f, -33.3125f, 20.0000f, 22, 34}, // 1ebe + {0.655762f, 0.839844f, 0.666016f, 0.854004f, -0.8125f, -28.2500f, 16.7500f, 21, 29}, // 1ebf + {0.916504f, 0.756836f, 0.927246f, 0.773438f, -1.0000f, -33.3125f, 20.0000f, 22, 34}, // 1ec0 + {0.315430f, 0.842773f, 0.325684f, 0.856934f, -2.9375f, -28.2500f, 16.7500f, 21, 29}, // 1ec1 + {0.865723f, 0.805664f, 0.875977f, 0.822266f, 0.3750f, -33.8125f, 20.0000f, 21, 34}, // 1ec2 + {0.832520f, 0.844238f, 0.842285f, 0.858887f, -0.8125f, -28.7500f, 16.6875f, 20, 30}, // 1ec3 + {0.430664f, 0.747070f, 0.440918f, 0.764648f, 0.3750f, -35.6250f, 20.0000f, 21, 36}, // 1ec4 + {0.263672f, 0.847168f, 0.272949f, 0.862305f, -0.8125f, -30.5625f, 16.7500f, 19, 31}, // 1ec5 + {0.533203f, 0.722656f, 0.543457f, 0.741211f, 0.3750f, -30.9375f, 20.0000f, 21, 38}, // 1ec6 + {0.067383f, 0.833008f, 0.076660f, 0.849121f, -0.8125f, -25.8750f, 16.7500f, 19, 33}, // 1ec7 + {0.994141f, 0.308594f, 0.999512f, 0.324219f, -1.0625f, -32.0000f, 8.3125f, 11, 32}, // 1ec8 + {0.543457f, 0.035645f, 0.548828f, 0.048828f, -1.0625f, -26.6250f, 8.3125f, 11, 27}, // 1ec9 + {0.996094f, 0.212891f, 0.999512f, 0.228516f, 0.7500f, -25.4375f, 8.3750f, 7, 32}, // 1eca + {0.995117f, 0.543457f, 0.998535f, 0.559082f, 0.0000f, -25.4375f, 6.6875f, 7, 32}, // 1ecb + {0.535645f, 0.706055f, 0.547852f, 0.722168f, -0.6250f, -25.8125f, 23.3125f, 25, 33}, // 1ecc + {0.989258f, 0.877930f, 0.998535f, 0.891113f, -0.9375f, -19.8750f, 16.6875f, 19, 27}, // 1ecd + {0.917480f, 0.706055f, 0.929688f, 0.722168f, -0.6250f, -32.0000f, 23.3125f, 25, 33}, // 1ece + {0.000000f, 0.878418f, 0.009277f, 0.891602f, -0.9375f, -26.6250f, 16.6875f, 19, 27}, // 1ecf + {0.509277f, 0.688965f, 0.521484f, 0.705566f, -0.6250f, -33.3125f, 23.3125f, 25, 34}, // 1ed0 + {0.392578f, 0.842773f, 0.402832f, 0.856934f, -0.9375f, -28.2500f, 16.6875f, 21, 29}, // 1ed1 + {0.538086f, 0.688965f, 0.550293f, 0.705566f, -0.6250f, -33.3125f, 23.3125f, 25, 34}, // 1ed2 + {0.403320f, 0.842773f, 0.413574f, 0.856934f, -2.9375f, -28.2500f, 16.6875f, 21, 29}, // 1ed3 + {0.872559f, 0.664063f, 0.884766f, 0.681152f, -0.6250f, -33.8125f, 23.3125f, 25, 35}, // 1ed4 + {0.578125f, 0.831543f, 0.588379f, 0.846191f, -0.9375f, -28.7500f, 16.6875f, 21, 30}, // 1ed5 + {0.793945f, 0.604492f, 0.806152f, 0.622070f, -0.6250f, -35.6250f, 23.3125f, 25, 36}, // 1ed6 + {0.693359f, 0.847168f, 0.702637f, 0.862305f, -0.9375f, -30.5625f, 16.6875f, 19, 31}, // 1ed7 + {0.249512f, 0.504395f, 0.261719f, 0.522949f, -0.6250f, -30.9375f, 23.3125f, 25, 38}, // 1ed8 + {0.077148f, 0.833008f, 0.086426f, 0.849121f, -0.9375f, -25.8750f, 16.6875f, 19, 33}, // 1ed9 + {0.904297f, 0.705566f, 0.916992f, 0.721191f, -0.6250f, -31.0000f, 23.2500f, 26, 32}, // 1eda + {0.507324f, 0.874023f, 0.517090f, 0.887207f, -0.9375f, -25.8750f, 16.6875f, 20, 27}, // 1edb + {0.041504f, 0.706055f, 0.054199f, 0.721680f, -0.6250f, -31.0000f, 23.2500f, 26, 32}, // 1edc + {0.542480f, 0.874023f, 0.552246f, 0.887207f, -0.9375f, -25.8750f, 16.6875f, 20, 27}, // 1edd + {0.632813f, 0.687988f, 0.645508f, 0.704102f, -0.6250f, -32.0000f, 23.2500f, 26, 33}, // 1ede + {0.564453f, 0.874023f, 0.574219f, 0.887207f, -0.9375f, -26.6250f, 16.6875f, 20, 27}, // 1edf + {0.693848f, 0.251465f, 0.706543f, 0.266602f, -0.6250f, -30.5000f, 23.2500f, 26, 31}, // 1ee0 + {0.932129f, 0.877441f, 0.941895f, 0.890137f, -0.9375f, -25.4375f, 16.6875f, 20, 26}, // 1ee1 + {0.697266f, 0.663086f, 0.709961f, 0.679688f, -0.6250f, -27.0000f, 23.2500f, 26, 34}, // 1ee2 + {0.288574f, 0.851074f, 0.298340f, 0.865234f, -0.9375f, -22.1875f, 16.6875f, 20, 29}, // 1ee3 + {0.000000f, 0.818848f, 0.010254f, 0.834473f, 0.3750f, -25.4375f, 21.6250f, 21, 32}, // 1ee4 + {0.589844f, 0.903809f, 0.598145f, 0.916504f, 0.0000f, -19.5000f, 16.6875f, 17, 26}, // 1ee5 + {0.889648f, 0.814941f, 0.899902f, 0.831055f, 0.3750f, -32.0000f, 21.6250f, 21, 33}, // 1ee6 + {0.252441f, 0.902344f, 0.260742f, 0.915527f, 0.0000f, -26.6250f, 16.6875f, 17, 27}, // 1ee7 + {0.202148f, 0.722656f, 0.214355f, 0.738281f, 0.3750f, -30.9375f, 23.2500f, 25, 32}, // 1ee8 + {0.441406f, 0.135254f, 0.451660f, 0.148438f, 0.0000f, -25.8125f, 18.6250f, 21, 27}, // 1ee9 + {0.461426f, 0.722656f, 0.473633f, 0.738281f, 0.3750f, -30.9375f, 23.2500f, 25, 32}, // 1eea + {0.505859f, 0.148438f, 0.516113f, 0.161621f, 0.0000f, -25.8125f, 18.6250f, 21, 27}, // 1eeb + {0.930176f, 0.706055f, 0.942383f, 0.722168f, 0.3750f, -32.0000f, 23.2500f, 25, 33}, // 1eec + {0.785156f, 0.857910f, 0.795410f, 0.871094f, 0.0000f, -26.6250f, 18.6250f, 21, 27}, // 1eed + {0.573730f, 0.734863f, 0.585938f, 0.750000f, 0.3750f, -30.5000f, 23.2500f, 25, 31}, // 1eee + {0.073242f, 0.865723f, 0.083496f, 0.878418f, 0.0000f, -25.4375f, 18.6250f, 21, 26}, // 1eef + {0.028809f, 0.689453f, 0.041016f, 0.706055f, 0.3750f, -27.0000f, 23.2500f, 25, 34}, // 1ef0 + {0.414063f, 0.842773f, 0.424316f, 0.856934f, 0.0000f, -22.5625f, 18.6250f, 21, 29}, // 1ef1 + {0.148926f, 0.757324f, 0.160645f, 0.772461f, -1.8750f, -31.0000f, 20.0625f, 24, 31}, // 1ef2 + {0.305664f, 0.833008f, 0.314941f, 0.849121f, -1.5625f, -25.8125f, 15.0000f, 19, 33}, // 1ef3 + {0.530762f, 0.741699f, 0.542480f, 0.757324f, -1.8750f, -25.4375f, 20.0625f, 24, 32}, // 1ef4 + {0.823242f, 0.889648f, 0.832520f, 0.902344f, -1.5625f, -19.5000f, 15.0000f, 19, 26}, // 1ef5 + {0.987793f, 0.035645f, 0.999512f, 0.051758f, -1.8750f, -32.0625f, 20.0000f, 24, 33}, // 1ef6 + {0.186523f, 0.833496f, 0.195801f, 0.849609f, -1.5625f, -26.6250f, 15.0000f, 19, 33}, // 1ef7 + {0.799316f, 0.757324f, 0.811035f, 0.772461f, -1.8750f, -30.5000f, 20.0000f, 24, 31}, // 1ef8 + {0.370605f, 0.843262f, 0.379883f, 0.858887f, -1.5000f, -25.4375f, 15.0000f, 19, 32}, // 1ef9 +// RANGE: 0x3000 - 0x3040, start 0x48e {0.000000f, 0.000000f, 0.000488f, 0.000488f, -2.0000f, -4.0000f, 30.0000f, 1, 1}, // 3000 - {0.742188f, 0.692871f, 0.748047f, 0.698730f, 0.8125f, -9.0625f, 30.0000f, 12, 12}, // 3001 - {0.787598f, 0.697754f, 0.793945f, 0.704102f, 0.5625f, -11.0625f, 30.0000f, 13, 13}, // 3002 - {0.558594f, 0.736328f, 0.566406f, 0.743164f, 7.1250f, -19.8125f, 30.0000f, 16, 14}, // 3003 - {0.939941f, 0.632813f, 0.954102f, 0.647461f, 1.0000f, -28.0000f, 30.0000f, 29, 30}, // 3004 - {0.512207f, 0.147949f, 0.523926f, 0.161621f, 2.0625f, -27.3750f, 30.0000f, 24, 28}, // 3005 - {0.197754f, 0.589355f, 0.209961f, 0.601563f, 2.4375f, -24.8750f, 30.0000f, 25, 25}, // 3006 - {0.499512f, 0.661133f, 0.513672f, 0.675293f, 1.1875f, -27.7500f, 30.0000f, 29, 29}, // 3007 - {0.992188f, 0.209961f, 0.999512f, 0.225586f, 15.5625f, -29.1250f, 30.0000f, 15, 32}, // 3008 - {0.167480f, 0.816895f, 0.174805f, 0.832520f, 0.3125f, -29.1250f, 30.0000f, 15, 32}, // 3009 - {0.519043f, 0.780273f, 0.527832f, 0.795898f, 13.0000f, -29.1250f, 30.0000f, 18, 32}, // 300a - {0.528320f, 0.780273f, 0.537109f, 0.795898f, -0.5625f, -29.1250f, 30.0000f, 18, 32}, // 300b - {0.206543f, 0.720215f, 0.213867f, 0.729492f, 14.7500f, -29.1250f, 30.0000f, 15, 19}, // 300c - {0.664063f, 0.728516f, 0.671387f, 0.737793f, 1.0000f, -16.6250f, 30.0000f, 15, 19}, // 300d - {0.461914f, 0.843262f, 0.469727f, 0.852539f, 14.7500f, -29.0625f, 30.0000f, 16, 19}, // 300e - {0.470215f, 0.843262f, 0.478027f, 0.852539f, 0.0625f, -16.6875f, 30.0000f, 16, 19}, // 300f - {0.891113f, 0.032715f, 0.897461f, 0.048340f, 16.3125f, -29.1250f, 30.0000f, 13, 32}, // 3010 - {0.554199f, 0.828125f, 0.560547f, 0.843750f, 1.0000f, -29.1250f, 30.0000f, 13, 32}, // 3011 - {0.378906f, 0.759766f, 0.390625f, 0.772949f, 3.1250f, -26.0625f, 30.0000f, 24, 27}, // 3012 - {0.430664f, 0.751953f, 0.443359f, 0.764648f, 2.3125f, -26.5000f, 30.0000f, 26, 26}, // 3013 - {0.306152f, 0.829102f, 0.312500f, 0.844727f, 16.7500f, -29.3750f, 30.0000f, 13, 32}, // 3014 - {0.392578f, 0.829102f, 0.398926f, 0.844727f, 1.0000f, -29.3750f, 30.0000f, 13, 32}, // 3015 - {0.318359f, 0.817383f, 0.325684f, 0.833008f, 15.0625f, -29.3750f, 30.0000f, 15, 32}, // 3016 - {0.404785f, 0.817383f, 0.412109f, 0.833008f, 0.0000f, -29.3750f, 30.0000f, 15, 32}, // 3017 - {0.994141f, 0.032227f, 0.999512f, 0.047852f, 17.4375f, -29.0625f, 30.0000f, 11, 32}, // 3018 - {0.182129f, 0.840332f, 0.187500f, 0.855957f, 1.6875f, -29.0625f, 30.0000f, 11, 32}, // 3019 - {0.749512f, 0.829102f, 0.755859f, 0.844727f, 15.3125f, -28.6250f, 30.0000f, 13, 32}, // 301a - {0.191895f, 0.829590f, 0.198242f, 0.845215f, 1.6250f, -28.6250f, 30.0000f, 13, 32}, // 301b - {0.145508f, 0.170898f, 0.161133f, 0.175781f, -0.8750f, -18.0000f, 30.0000f, 32, 10}, // 301c - {0.041016f, 0.739746f, 0.048828f, 0.746582f, 14.0000f, -29.6250f, 30.0000f, 16, 14}, // 301d - {0.650391f, 0.720703f, 0.657715f, 0.727539f, 1.0000f, -29.6250f, 30.0000f, 15, 14}, // 301e - {0.641602f, 0.748047f, 0.649414f, 0.754883f, 3.3750f, -12.3125f, 30.0000f, 16, 14}, // 301f - {0.908203f, 0.587891f, 0.922363f, 0.599121f, 0.6875f, -24.6875f, 30.0000f, 29, 23}, // 3020 - {0.664063f, 0.430664f, 0.667480f, 0.442871f, 11.3125f, -25.5000f, 30.0000f, 7, 25}, // 3021 - {0.992676f, 0.558105f, 0.999512f, 0.569824f, 8.1250f, -25.4375f, 30.0000f, 14, 24}, // 3022 - {0.049316f, 0.818848f, 0.058594f, 0.831055f, 5.6250f, -25.5000f, 30.0000f, 19, 25}, // 3023 - {0.102051f, 0.782227f, 0.113281f, 0.794434f, 2.5625f, -25.2500f, 30.0000f, 23, 25}, // 3024 - {0.345215f, 0.821777f, 0.354004f, 0.834473f, 6.5625f, -26.4375f, 30.0000f, 18, 26}, // 3025 - {0.442871f, 0.031250f, 0.454590f, 0.039551f, 3.5000f, -24.1250f, 30.0000f, 24, 17}, // 3026 - {0.435059f, 0.153320f, 0.446777f, 0.163086f, 3.5000f, -24.7500f, 30.0000f, 24, 20}, // 3027 - {0.962402f, 0.787109f, 0.974121f, 0.798340f, 3.4375f, -25.2500f, 30.0000f, 24, 23}, // 3028 - {0.663086f, 0.766113f, 0.674805f, 0.778809f, 4.1250f, -26.3125f, 30.0000f, 24, 26}, // 3029 - {0.742188f, 0.699219f, 0.748047f, 0.705078f, 1.3125f, -11.9375f, 30.0000f, 12, 12}, // 302a - {0.122559f, 0.711914f, 0.128418f, 0.717773f, 1.3125f, -27.3125f, 30.0000f, 12, 12}, // 302b - {0.992676f, 0.727539f, 0.998535f, 0.733398f, 16.7500f, -27.3125f, 30.0000f, 12, 12}, // 302c - {0.450684f, 0.729980f, 0.456543f, 0.735840f, 16.7500f, -11.9375f, 30.0000f, 12, 12}, // 302d - {0.380371f, 0.621094f, 0.384766f, 0.625488f, 0.5625f, -17.8750f, 30.0000f, 9, 9}, // 302e - {0.302734f, 0.272949f, 0.307129f, 0.280273f, 0.5000f, -20.9375f, 30.0000f, 9, 15}, // 302f - {0.304688f, 0.333008f, 0.319336f, 0.337891f, 0.0000f, -18.3750f, 30.0000f, 30, 10}, // 3030 - {0.724121f, 0.787109f, 0.732910f, 0.802246f, 6.5000f, -28.3125f, 30.0000f, 18, 31}, // 3031 - {0.193359f, 0.080078f, 0.205566f, 0.095215f, 4.0000f, -28.4375f, 30.0000f, 25, 31}, // 3032 - {0.378906f, 0.773438f, 0.389160f, 0.787598f, 3.1875f, -27.5000f, 30.0000f, 21, 29}, // 3033 - {0.649902f, 0.675293f, 0.663574f, 0.689453f, 1.8125f, -27.5000f, 30.0000f, 28, 29}, // 3034 - {0.751953f, 0.784668f, 0.761230f, 0.799316f, 4.9375f, -27.9375f, 30.0000f, 19, 30}, // 3035 - {0.531250f, 0.661133f, 0.545410f, 0.675293f, 1.1875f, -27.7500f, 30.0000f, 29, 29}, // 3036 - {0.178711f, 0.176758f, 0.193359f, 0.191895f, -0.1875f, -28.8750f, 30.0000f, 30, 31}, // 3037 - {0.349609f, 0.733398f, 0.362793f, 0.746582f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3038 - {0.580566f, 0.733398f, 0.593750f, 0.746582f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3039 - {0.608398f, 0.733398f, 0.621582f, 0.746582f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303a - {0.976074f, 0.733398f, 0.989258f, 0.746582f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303b - {0.048828f, 0.733887f, 0.062012f, 0.747070f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303c - {0.183105f, 0.733887f, 0.196289f, 0.747070f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303d - {0.911621f, 0.733887f, 0.924805f, 0.747070f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303e - {0.718750f, 0.760742f, 0.728516f, 0.776367f, 5.1875f, -29.0625f, 30.0000f, 20, 32}, // 303f -// RANGE: 0x3041 - 0x3098, start 0x39a - {0.113770f, 0.782227f, 0.125000f, 0.794434f, 3.5625f, -25.6250f, 30.0000f, 23, 25}, // 3041 - {0.698242f, 0.081055f, 0.711426f, 0.095703f, 1.3750f, -27.4375f, 30.0000f, 27, 30}, // 3042 - {0.779785f, 0.811035f, 0.790527f, 0.822266f, 4.5000f, -24.1250f, 30.0000f, 22, 23}, // 3043 - {0.674316f, 0.242188f, 0.687012f, 0.255859f, 2.3125f, -26.8125f, 30.0000f, 26, 28}, // 3044 - {0.296875f, 0.811523f, 0.307129f, 0.823242f, 3.6875f, -24.6875f, 30.0000f, 21, 24}, // 3045 - {0.448730f, 0.749512f, 0.460938f, 0.763184f, 1.3750f, -26.7500f, 30.0000f, 25, 28}, // 3046 - {0.354492f, 0.576660f, 0.366211f, 0.588379f, 3.0000f, -25.3125f, 30.0000f, 24, 24}, // 3047 - {0.161133f, 0.675781f, 0.174805f, 0.689941f, 0.6875f, -27.6250f, 30.0000f, 28, 29}, // 3048 - {0.376953f, 0.788086f, 0.388184f, 0.799805f, 3.5625f, -25.1250f, 30.0000f, 23, 24}, // 3049 - {0.650391f, 0.460938f, 0.663574f, 0.475098f, 1.0625f, -27.9375f, 30.0000f, 27, 29}, // 304a - {0.684570f, 0.097168f, 0.698242f, 0.111816f, 0.3750f, -28.1875f, 30.0000f, 28, 30}, // 304b - {0.616699f, 0.017578f, 0.631836f, 0.032227f, -0.2500f, -28.4375f, 30.0000f, 31, 30}, // 304c - {0.463379f, 0.692383f, 0.476074f, 0.707031f, 0.9375f, -28.3750f, 30.0000f, 26, 30}, // 304d - {0.159668f, 0.224609f, 0.174316f, 0.239258f, 1.0000f, -29.0000f, 30.0000f, 30, 30}, // 304e - {0.330078f, 0.760254f, 0.341309f, 0.773926f, 2.3125f, -27.3125f, 30.0000f, 23, 28}, // 304f - {0.530273f, 0.193848f, 0.543945f, 0.208496f, 2.3125f, -28.6250f, 30.0000f, 28, 30}, // 3050 - {0.886719f, 0.676758f, 0.899902f, 0.691406f, 2.8125f, -27.5000f, 30.0000f, 27, 30}, // 3051 - {0.273926f, 0.210449f, 0.288574f, 0.226074f, 0.8750f, -29.1875f, 30.0000f, 30, 32}, // 3052 - {0.461426f, 0.757324f, 0.473633f, 0.770020f, 2.8750f, -25.5000f, 30.0000f, 25, 26}, // 3053 - {0.553223f, 0.051270f, 0.566406f, 0.064941f, 1.4375f, -28.2500f, 30.0000f, 27, 28}, // 3054 - {0.284180f, 0.706543f, 0.296875f, 0.720703f, 0.8750f, -27.6875f, 30.0000f, 26, 29}, // 3055 - {0.441895f, 0.633301f, 0.456055f, 0.647949f, 0.7500f, -28.6250f, 30.0000f, 29, 30}, // 3056 - {0.091309f, 0.655273f, 0.103027f, 0.668945f, 4.1875f, -27.1250f, 30.0000f, 24, 28}, // 3057 - {0.132324f, 0.692871f, 0.145020f, 0.707520f, 3.5000f, -28.6250f, 30.0000f, 26, 30}, // 3058 - {0.800781f, 0.288086f, 0.814453f, 0.302734f, 1.4375f, -27.1875f, 30.0000f, 28, 30}, // 3059 - {0.876953f, 0.064941f, 0.891113f, 0.080566f, 0.6250f, -29.8750f, 30.0000f, 29, 32}, // 305a - {0.539551f, 0.067383f, 0.553223f, 0.081055f, 0.9375f, -26.8125f, 30.0000f, 28, 28}, // 305b - {0.513672f, 0.351074f, 0.528809f, 0.366211f, 0.1250f, -29.9375f, 30.0000f, 31, 31}, // 305c - {0.434570f, 0.274414f, 0.448242f, 0.288086f, 1.0625f, -26.5625f, 30.0000f, 28, 28}, // 305d - {0.048340f, 0.332031f, 0.062988f, 0.346680f, 0.3750f, -28.2500f, 30.0000f, 30, 30}, // 305e - {0.713379f, 0.690430f, 0.726563f, 0.704590f, 1.5625f, -27.9375f, 30.0000f, 27, 29}, // 305f - {0.545898f, 0.661133f, 0.560059f, 0.675293f, 0.6250f, -28.2500f, 30.0000f, 29, 29}, // 3060 - {0.145508f, 0.707031f, 0.158203f, 0.721191f, 2.2500f, -28.0000f, 30.0000f, 26, 29}, // 3061 - {0.571777f, 0.081543f, 0.585449f, 0.096680f, 1.2500f, -29.8125f, 30.0000f, 28, 31}, // 3062 - {0.354004f, 0.245605f, 0.364746f, 0.254883f, 3.1875f, -22.1250f, 30.0000f, 22, 19}, // 3063 - {0.729004f, 0.775879f, 0.742188f, 0.786621f, 1.6250f, -23.3750f, 30.0000f, 27, 22}, // 3064 - {0.393066f, 0.675781f, 0.406738f, 0.689941f, 0.8750f, -30.1875f, 30.0000f, 28, 29}, // 3065 - {0.742188f, 0.705078f, 0.755859f, 0.718262f, 0.6250f, -25.6250f, 30.0000f, 28, 27}, // 3066 - {0.458984f, 0.432129f, 0.473145f, 0.445313f, 0.6250f, -25.6250f, 30.0000f, 29, 27}, // 3067 - {0.592773f, 0.759766f, 0.604492f, 0.772949f, 2.8750f, -27.3125f, 30.0000f, 24, 27}, // 3068 - {0.763184f, 0.690430f, 0.776367f, 0.704590f, 2.8750f, -28.3750f, 30.0000f, 27, 29}, // 3069 - {0.560547f, 0.661133f, 0.574707f, 0.675293f, 0.3750f, -28.0000f, 30.0000f, 29, 29}, // 306a - {0.619141f, 0.446777f, 0.632324f, 0.460449f, 1.8750f, -27.4375f, 30.0000f, 27, 28}, // 306b - {0.748047f, 0.050781f, 0.762207f, 0.064453f, 1.1250f, -27.5000f, 30.0000f, 29, 28}, // 306c - {0.850586f, 0.350586f, 0.864746f, 0.364258f, 0.6250f, -27.2500f, 30.0000f, 29, 28}, // 306d - {0.705078f, 0.748047f, 0.718262f, 0.760742f, 1.4375f, -25.4375f, 30.0000f, 27, 26}, // 306e - {0.499023f, 0.675781f, 0.512695f, 0.689941f, 1.3125f, -27.2500f, 30.0000f, 28, 29}, // 306f - {0.984863f, 0.194336f, 0.999512f, 0.209473f, 0.5000f, -29.2500f, 30.0000f, 30, 31}, // 3070 - {0.224121f, 0.244141f, 0.238770f, 0.259277f, 0.8125f, -29.3125f, 30.0000f, 30, 31}, // 3071 - {0.795410f, 0.690430f, 0.809570f, 0.703613f, 1.6250f, -26.3125f, 30.0000f, 29, 27}, // 3072 - {0.866211f, 0.633301f, 0.880371f, 0.647949f, 0.6250f, -29.2500f, 30.0000f, 29, 30}, // 3073 - {0.602539f, 0.033203f, 0.616699f, 0.048340f, 1.0625f, -29.8750f, 30.0000f, 29, 31}, // 3074 - {0.967285f, 0.676758f, 0.981934f, 0.689941f, 0.1875f, -26.7500f, 30.0000f, 30, 27}, // 3075 - {0.274902f, 0.573730f, 0.289551f, 0.588379f, -0.1250f, -29.2500f, 30.0000f, 30, 30}, // 3076 - {0.608398f, 0.351074f, 0.623535f, 0.366211f, -0.5625f, -29.8750f, 30.0000f, 31, 31}, // 3077 - {0.035645f, 0.764648f, 0.049805f, 0.775391f, 0.5625f, -23.8750f, 30.0000f, 29, 22}, // 3078 - {0.964355f, 0.690430f, 0.978516f, 0.703613f, 0.5625f, -28.1875f, 30.0000f, 29, 27}, // 3079 - {0.372559f, 0.690918f, 0.386719f, 0.704102f, -0.0625f, -28.8750f, 30.0000f, 29, 27}, // 307a - {0.415527f, 0.353516f, 0.429199f, 0.367188f, 1.2500f, -27.1875f, 30.0000f, 28, 28}, // 307b - {0.339355f, 0.576660f, 0.354004f, 0.591309f, 0.3125f, -28.7500f, 30.0000f, 30, 30}, // 307c - {0.000000f, 0.578125f, 0.014648f, 0.592773f, 0.8125f, -28.8750f, 30.0000f, 30, 30}, // 307d - {0.530273f, 0.675781f, 0.543945f, 0.689941f, 1.7500f, -27.9375f, 30.0000f, 28, 29}, // 307e - {0.544434f, 0.675781f, 0.558105f, 0.689941f, 1.4375f, -27.1875f, 30.0000f, 28, 29}, // 307f - {0.558594f, 0.675781f, 0.572266f, 0.689941f, 1.6250f, -27.6875f, 30.0000f, 28, 29}, // 3080 - {0.586426f, 0.690918f, 0.599609f, 0.705078f, 1.8750f, -27.9375f, 30.0000f, 27, 29}, // 3081 - {0.756348f, 0.705078f, 0.769531f, 0.718750f, 1.3125f, -27.6875f, 30.0000f, 27, 28}, // 3082 - {0.647949f, 0.788086f, 0.659180f, 0.799805f, 3.1250f, -25.3125f, 30.0000f, 23, 24}, // 3083 - {0.718262f, 0.675781f, 0.731934f, 0.689941f, 0.9375f, -27.6875f, 30.0000f, 28, 29}, // 3084 - {0.771973f, 0.792969f, 0.782715f, 0.805176f, 4.0625f, -25.3750f, 30.0000f, 22, 25}, // 3085 - {0.132813f, 0.677734f, 0.145996f, 0.692383f, 2.0000f, -27.7500f, 30.0000f, 27, 30}, // 3086 - {0.296875f, 0.799805f, 0.308105f, 0.811035f, 3.7500f, -25.0000f, 30.0000f, 23, 23}, // 3087 - {0.013672f, 0.734375f, 0.026855f, 0.747559f, 1.5000f, -27.4375f, 30.0000f, 27, 27}, // 3088 - {0.783691f, 0.749512f, 0.795898f, 0.763184f, 2.3125f, -27.4375f, 30.0000f, 25, 28}, // 3089 - {0.669434f, 0.145508f, 0.680176f, 0.160156f, 3.8125f, -27.1250f, 30.0000f, 22, 30}, // 308a - {0.238281f, 0.734375f, 0.251465f, 0.747559f, 0.4375f, -27.0000f, 30.0000f, 27, 27}, // 308b - {0.721680f, 0.661133f, 0.735840f, 0.675293f, 1.1250f, -27.2500f, 30.0000f, 29, 29}, // 308c - {0.582520f, 0.705566f, 0.595703f, 0.719238f, 1.0000f, -26.8125f, 30.0000f, 27, 28}, // 308d - {0.612793f, 0.780273f, 0.624512f, 0.791992f, 2.7500f, -25.0625f, 30.0000f, 24, 24}, // 308e - {0.030273f, 0.583008f, 0.043945f, 0.596680f, 0.3750f, -27.5000f, 30.0000f, 28, 28}, // 308f - {0.379395f, 0.734375f, 0.392578f, 0.747559f, 1.5625f, -26.3750f, 30.0000f, 27, 27}, // 3090 - {0.215820f, 0.495117f, 0.229980f, 0.508789f, 0.5625f, -27.2500f, 30.0000f, 29, 28}, // 3091 - {0.810059f, 0.690918f, 0.823242f, 0.705078f, 1.4375f, -28.1875f, 30.0000f, 27, 29}, // 3092 - {0.787109f, 0.523926f, 0.801270f, 0.537598f, 0.6875f, -27.3750f, 30.0000f, 29, 28}, // 3093 - {0.226563f, 0.633789f, 0.241211f, 0.647949f, 1.0625f, -27.6250f, 30.0000f, 30, 29}, // 3094 - {0.594238f, 0.734375f, 0.607422f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3095 - {0.622070f, 0.734375f, 0.635254f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3096 - {0.635742f, 0.734375f, 0.648926f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3097 -// RANGE: 0x3099 - 0x30a0, start 0x3f1 - {0.140137f, 0.186523f, 0.145508f, 0.191895f, 17.1875f, -28.2500f, 30.0000f, 11, 11}, // 3099 - {0.126953f, 0.202148f, 0.132324f, 0.207520f, 19.0625f, -29.8750f, 30.0000f, 11, 11}, // 309a - {0.381348f, 0.304688f, 0.386719f, 0.310059f, 13.0625f, -28.2500f, 30.0000f, 11, 11}, // 309b - {0.353516f, 0.446777f, 0.358887f, 0.452148f, 12.6875f, -29.8750f, 30.0000f, 11, 11}, // 309c - {0.675293f, 0.766113f, 0.687012f, 0.778809f, 2.5625f, -26.3750f, 30.0000f, 24, 26}, // 309d - {0.559082f, 0.757324f, 0.571289f, 0.770020f, 2.5625f, -26.3750f, 30.0000f, 25, 26}, // 309e - {0.712402f, 0.734375f, 0.725586f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 309f -// RANGE: 0x30a0 - 0x3100, start 0x3f8 - {0.811035f, 0.734375f, 0.824219f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 30a0 - {0.388672f, 0.799805f, 0.399902f, 0.811035f, 3.9375f, -23.9375f, 30.0000f, 23, 23}, // 30a1 - {0.768555f, 0.661621f, 0.782715f, 0.675781f, 0.8125f, -26.5625f, 30.0000f, 29, 29}, // 30a2 - {0.385254f, 0.811523f, 0.395508f, 0.823242f, 4.5000f, -25.1250f, 30.0000f, 21, 24}, // 30a3 - {0.187012f, 0.692871f, 0.199707f, 0.707520f, 1.6250f, -28.0000f, 30.0000f, 26, 30}, // 30a4 - {0.518555f, 0.811523f, 0.528809f, 0.823242f, 4.7500f, -24.8750f, 30.0000f, 21, 24}, // 30a5 - {0.189941f, 0.677734f, 0.203125f, 0.692383f, 1.7500f, -28.1250f, 30.0000f, 27, 30}, // 30a6 - {0.383301f, 0.101563f, 0.394531f, 0.111816f, 3.6250f, -22.8750f, 30.0000f, 23, 21}, // 30a7 - {0.684570f, 0.677734f, 0.699219f, 0.690918f, 0.3750f, -26.0625f, 30.0000f, 30, 27}, // 30a8 - {0.033203f, 0.789063f, 0.044922f, 0.800293f, 3.5000f, -24.5625f, 30.0000f, 24, 23}, // 30a9 - {0.105957f, 0.578125f, 0.120605f, 0.592773f, 0.8750f, -27.6875f, 30.0000f, 30, 30}, // 30aa - {0.478027f, 0.369141f, 0.491699f, 0.383789f, 0.5625f, -27.8750f, 30.0000f, 28, 30}, // 30ab - {0.911621f, 0.352051f, 0.925781f, 0.367188f, 0.5625f, -28.9375f, 30.0000f, 29, 31}, // 30ac - {0.241699f, 0.633789f, 0.255859f, 0.648438f, 0.1875f, -28.1250f, 30.0000f, 29, 30}, // 30ad - {0.888672f, 0.478027f, 0.903320f, 0.493164f, 0.0625f, -28.6250f, 30.0000f, 30, 31}, // 30ae - {0.699707f, 0.677734f, 0.712891f, 0.692383f, 1.5625f, -28.4375f, 30.0000f, 27, 30}, // 30af - {0.984863f, 0.256836f, 0.999512f, 0.272461f, 0.3125f, -29.5000f, 30.0000f, 30, 32}, // 30b0 - {0.258789f, 0.581055f, 0.273438f, 0.595703f, -0.1250f, -28.4375f, 30.0000f, 30, 30}, // 30b1 - {0.199707f, 0.479492f, 0.214355f, 0.494629f, -0.1250f, -29.1250f, 30.0000f, 30, 31}, // 30b2 - {0.824707f, 0.734375f, 0.837891f, 0.747559f, 0.8750f, -26.0625f, 30.0000f, 27, 27}, // 30b3 - {0.418945f, 0.552734f, 0.433105f, 0.568359f, 0.4375f, -30.3125f, 30.0000f, 29, 32}, // 30b4 - {0.349121f, 0.633789f, 0.363281f, 0.648438f, 0.5000f, -27.6250f, 30.0000f, 29, 30}, // 30b5 - {0.796387f, 0.413086f, 0.812012f, 0.427734f, -0.1250f, -28.0000f, 30.0000f, 32, 30}, // 30b6 - {0.060059f, 0.662109f, 0.074219f, 0.676270f, 0.4375f, -27.6875f, 30.0000f, 29, 29}, // 30b7 - {0.314453f, 0.634277f, 0.328613f, 0.648926f, 0.3125f, -28.0000f, 30.0000f, 29, 30}, // 30b8 - {0.344238f, 0.648926f, 0.359375f, 0.662598f, 0.4375f, -25.8750f, 30.0000f, 31, 28}, // 30b9 - {0.858887f, 0.177246f, 0.874023f, 0.192871f, -0.3750f, -30.0625f, 30.0000f, 31, 32}, // 30ba - {0.765137f, 0.676270f, 0.779297f, 0.689941f, 0.5625f, -27.6250f, 30.0000f, 29, 28}, // 30bb - {0.207520f, 0.662109f, 0.221680f, 0.676270f, 0.4375f, -28.0625f, 30.0000f, 29, 29}, // 30bc - {0.885254f, 0.707031f, 0.897949f, 0.721191f, 1.9375f, -27.4375f, 30.0000f, 26, 29}, // 30bd - {0.585449f, 0.065430f, 0.598633f, 0.080566f, 1.8750f, -28.9375f, 30.0000f, 27, 31}, // 30be - {0.691895f, 0.692871f, 0.704590f, 0.707520f, 1.5625f, -28.1875f, 30.0000f, 26, 30}, // 30bf - {0.256348f, 0.273438f, 0.270996f, 0.289063f, -0.2500f, -29.8125f, 30.0000f, 30, 32}, // 30c0 - {0.214844f, 0.479492f, 0.229492f, 0.494629f, 0.5625f, -28.4375f, 30.0000f, 30, 31}, // 30c1 - {0.296387f, 0.480957f, 0.311035f, 0.496094f, 0.3125f, -28.4375f, 30.0000f, 30, 31}, // 30c2 - {0.307617f, 0.817383f, 0.317871f, 0.828613f, 3.6250f, -23.9375f, 30.0000f, 21, 23}, // 30c3 - {0.979004f, 0.690918f, 0.992188f, 0.705078f, 0.6250f, -27.2500f, 30.0000f, 27, 29}, // 30c4 - {0.721680f, 0.256836f, 0.735352f, 0.271973f, 1.0000f, -28.8750f, 30.0000f, 28, 31}, // 30c5 - {0.847656f, 0.634277f, 0.862305f, 0.648438f, 0.1875f, -26.2500f, 30.0000f, 30, 29}, // 30c6 - {0.919922f, 0.602539f, 0.935059f, 0.616699f, 0.1875f, -26.7500f, 30.0000f, 31, 29}, // 30c7 - {0.591797f, 0.773438f, 0.602051f, 0.787598f, 6.6875f, -27.6250f, 30.0000f, 21, 29}, // 30c8 - {0.987305f, 0.765137f, 0.997559f, 0.779785f, 7.7500f, -27.7500f, 30.0000f, 21, 30}, // 30c9 - {0.000000f, 0.634766f, 0.014160f, 0.649414f, 0.4375f, -27.6250f, 30.0000f, 29, 30}, // 30ca - {0.642578f, 0.708008f, 0.657227f, 0.720215f, 0.3125f, -25.3750f, 30.0000f, 30, 25}, // 30cb - {0.615723f, 0.705566f, 0.628906f, 0.719238f, 1.4375f, -26.0625f, 30.0000f, 27, 28}, // 30cc - {0.795898f, 0.581055f, 0.810547f, 0.595703f, -0.0625f, -27.6250f, 30.0000f, 30, 30}, // 30cd - {0.295898f, 0.737305f, 0.308594f, 0.750977f, 1.8750f, -26.2500f, 30.0000f, 26, 28}, // 30ce - {0.014648f, 0.634766f, 0.029297f, 0.648926f, 0.1250f, -27.7500f, 30.0000f, 30, 29}, // 30cf - {0.935547f, 0.602539f, 0.950684f, 0.616699f, -0.6250f, -28.0000f, 30.0000f, 31, 29}, // 30d0 - {0.941895f, 0.351074f, 0.957031f, 0.366211f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 30d1 - {0.770508f, 0.743164f, 0.783203f, 0.756836f, 2.8750f, -27.1250f, 30.0000f, 26, 28}, // 30d2 - {0.983887f, 0.676270f, 0.997559f, 0.690430f, 2.4375f, -28.0000f, 30.0000f, 28, 29}, // 30d3 - {0.285156f, 0.662109f, 0.299316f, 0.676270f, 2.0625f, -28.0000f, 30.0000f, 29, 29}, // 30d4 - {0.000000f, 0.744629f, 0.012695f, 0.758301f, 2.5000f, -26.0000f, 30.0000f, 26, 28}, // 30d5 - {0.985352f, 0.112793f, 0.999512f, 0.128906f, 1.1875f, -30.6250f, 30.0000f, 29, 33}, // 30d6 - {0.874512f, 0.177246f, 0.889648f, 0.192871f, 0.6250f, -29.7500f, 30.0000f, 31, 32}, // 30d7 - {0.376953f, 0.748047f, 0.392090f, 0.759277f, -0.3125f, -23.5625f, 30.0000f, 31, 23}, // 30d8 - {0.921387f, 0.708008f, 0.936523f, 0.719727f, -0.3125f, -24.5625f, 30.0000f, 31, 24}, // 30d9 - {0.024414f, 0.708496f, 0.039551f, 0.720215f, -0.3125f, -24.5625f, 30.0000f, 31, 24}, // 30da - {0.678223f, 0.635742f, 0.692871f, 0.649902f, 0.0625f, -27.5625f, 30.0000f, 30, 29}, // 30db - {0.811035f, 0.581055f, 0.825684f, 0.595703f, 0.0625f, -28.6250f, 30.0000f, 30, 30}, // 30dc - {0.343750f, 0.483398f, 0.358398f, 0.498535f, 0.0625f, -29.5000f, 30.0000f, 30, 31}, // 30dd - {0.809082f, 0.705566f, 0.822754f, 0.718750f, 1.3750f, -25.8750f, 30.0000f, 28, 27}, // 30de - {0.056641f, 0.676758f, 0.070313f, 0.690918f, 1.0625f, -27.1250f, 30.0000f, 28, 29}, // 30df - {0.177734f, 0.636230f, 0.192383f, 0.650391f, 0.3750f, -27.8125f, 30.0000f, 30, 29}, // 30e0 - {0.427734f, 0.707520f, 0.440430f, 0.721680f, 1.1875f, -27.6250f, 30.0000f, 26, 29}, // 30e1 - {0.748047f, 0.677734f, 0.762695f, 0.690918f, 0.4375f, -26.1875f, 30.0000f, 30, 27}, // 30e2 - {0.948242f, 0.799805f, 0.958984f, 0.811523f, 4.0625f, -24.6250f, 30.0000f, 22, 24}, // 30e3 - {0.540527f, 0.413086f, 0.554199f, 0.427734f, 1.0625f, -28.0625f, 30.0000f, 28, 30}, // 30e4 - {0.399902f, 0.343262f, 0.411133f, 0.353516f, 3.3750f, -23.1250f, 30.0000f, 23, 21}, // 30e5 - {0.826660f, 0.677734f, 0.841309f, 0.690918f, 0.2500f, -25.9375f, 30.0000f, 30, 27}, // 30e6 - {0.036133f, 0.825195f, 0.046387f, 0.835449f, 4.1250f, -23.1875f, 30.0000f, 21, 21}, // 30e7 - {0.838379f, 0.734375f, 0.851563f, 0.747559f, 1.1250f, -25.9375f, 30.0000f, 27, 27}, // 30e8 - {0.206055f, 0.676758f, 0.219727f, 0.690918f, 1.0625f, -26.5000f, 30.0000f, 28, 29}, // 30e9 - {0.050293f, 0.764648f, 0.061035f, 0.778809f, 4.3750f, -27.0625f, 30.0000f, 22, 29}, // 30ea - {0.358887f, 0.483887f, 0.374023f, 0.498535f, -0.1875f, -27.6875f, 30.0000f, 31, 30}, // 30eb - {0.490723f, 0.746582f, 0.502930f, 0.760742f, 4.0625f, -27.6875f, 30.0000f, 25, 29}, // 30ec - {0.809570f, 0.748047f, 0.822266f, 0.761230f, 2.0000f, -25.9375f, 30.0000f, 26, 27}, // 30ed - {0.354492f, 0.822266f, 0.364746f, 0.833008f, 4.7500f, -23.0625f, 30.0000f, 21, 22}, // 30ee - {0.979004f, 0.705566f, 0.992188f, 0.719238f, 1.6875f, -25.9375f, 30.0000f, 27, 28}, // 30ef - {0.329102f, 0.638672f, 0.343750f, 0.652832f, 0.5000f, -27.5000f, 30.0000f, 30, 29}, // 30f0 - {0.921875f, 0.677734f, 0.936523f, 0.690918f, 0.2500f, -25.9375f, 30.0000f, 30, 27}, // 30f1 - {0.055176f, 0.691406f, 0.068359f, 0.705566f, 1.6250f, -26.6250f, 30.0000f, 27, 29}, // 30f2 - {0.491699f, 0.690430f, 0.505371f, 0.704102f, 1.1875f, -26.6250f, 30.0000f, 28, 28}, // 30f3 - {0.832520f, 0.304688f, 0.846191f, 0.319824f, 1.1875f, -29.1875f, 30.0000f, 28, 31}, // 30f4 - {0.374023f, 0.800293f, 0.384766f, 0.812012f, 3.9375f, -24.7500f, 30.0000f, 22, 24}, // 30f5 - {0.201660f, 0.789063f, 0.212891f, 0.800781f, 3.3750f, -24.8750f, 30.0000f, 23, 24}, // 30f6 - {0.107910f, 0.484375f, 0.122559f, 0.499512f, 0.7500f, -29.0625f, 30.0000f, 30, 31}, // 30f7 - {0.973633f, 0.351074f, 0.988770f, 0.366211f, 0.1875f, -29.3125f, 30.0000f, 31, 31}, // 30f8 - {0.143066f, 0.351563f, 0.158203f, 0.366699f, 0.4375f, -29.8750f, 30.0000f, 31, 31}, // 30f9 - {0.271973f, 0.289063f, 0.286621f, 0.304688f, 1.1875f, -29.4375f, 30.0000f, 30, 32}, // 30fa - {0.962402f, 0.622070f, 0.966797f, 0.626465f, 2.8125f, -17.8750f, 30.0000f, 9, 9}, // 30fb - {0.191895f, 0.239746f, 0.206543f, 0.243164f, 0.4375f, -16.9375f, 30.0000f, 30, 7}, // 30fc - {0.147949f, 0.819336f, 0.157227f, 0.831543f, 6.1250f, -24.0000f, 30.0000f, 19, 25}, // 30fd - {0.952637f, 0.784668f, 0.961914f, 0.799316f, 6.1250f, -28.2500f, 30.0000f, 19, 30}, // 30fe - {0.925293f, 0.734375f, 0.938477f, 0.747559f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 30ff -// RANGE: 0x31f0 - 0x3200, start 0x458 - {0.220215f, 0.734863f, 0.233398f, 0.748047f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f0 - {0.268555f, 0.734863f, 0.281738f, 0.748047f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f1 - {0.136230f, 0.735352f, 0.149414f, 0.748535f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f2 - {0.874512f, 0.735352f, 0.887695f, 0.748535f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f3 - {0.421387f, 0.735840f, 0.434570f, 0.749023f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f4 - {0.450684f, 0.735840f, 0.463867f, 0.749023f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f5 - {0.783203f, 0.735840f, 0.796387f, 0.749023f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f6 - {0.938965f, 0.735840f, 0.952148f, 0.749023f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f7 - {0.952637f, 0.735840f, 0.965820f, 0.749023f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f8 - {0.119141f, 0.736328f, 0.132324f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f9 - {0.363281f, 0.736328f, 0.376465f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fa - {0.517578f, 0.736328f, 0.530762f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fb - {0.531250f, 0.736328f, 0.544434f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fc - {0.544922f, 0.736328f, 0.558105f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fd - {0.888184f, 0.736328f, 0.901367f, 0.749512f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fe - {0.168945f, 0.736816f, 0.182129f, 0.750000f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31ff -// RANGE: 0x4e00 - 0xa000, start 0x468 - {0.303711f, 0.312988f, 0.317383f, 0.316406f, 1.6250f, -17.1875f, 30.0000f, 28, 7}, // 4e00 - {0.271973f, 0.635742f, 0.286133f, 0.650391f, 0.9375f, -27.0625f, 30.0000f, 29, 30}, // 4e01 + {0.820313f, 0.161621f, 0.826172f, 0.167480f, 0.8125f, -9.0625f, 30.0000f, 12, 12}, // 3001 + {0.625000f, 0.067871f, 0.631348f, 0.074219f, 0.5625f, -11.0625f, 30.0000f, 13, 13}, // 3002 + {0.738281f, 0.247070f, 0.746094f, 0.253906f, 7.1250f, -19.8125f, 30.0000f, 16, 14}, // 3003 + {0.300293f, 0.666992f, 0.314453f, 0.681641f, 1.0000f, -28.0000f, 30.0000f, 29, 30}, // 3004 + {0.075684f, 0.818848f, 0.087402f, 0.832520f, 2.0625f, -27.3750f, 30.0000f, 24, 28}, // 3005 + {0.709961f, 0.266602f, 0.722168f, 0.278809f, 2.4375f, -24.8750f, 30.0000f, 25, 25}, // 3006 + {0.698730f, 0.690430f, 0.712891f, 0.704590f, 1.1875f, -27.7500f, 30.0000f, 29, 29}, // 3007 + {0.192383f, 0.077637f, 0.199707f, 0.093262f, 15.5625f, -29.1250f, 30.0000f, 15, 32}, // 3008 + {0.289063f, 0.112305f, 0.296387f, 0.127930f, 0.3125f, -29.1250f, 30.0000f, 15, 32}, // 3009 + {0.726563f, 0.851074f, 0.735352f, 0.866699f, 13.0000f, -29.1250f, 30.0000f, 18, 32}, // 300a + {0.735840f, 0.851074f, 0.744629f, 0.866699f, -0.5625f, -29.1250f, 30.0000f, 18, 32}, // 300b + {0.562500f, 0.081055f, 0.569824f, 0.090332f, 14.7500f, -29.1250f, 30.0000f, 15, 19}, // 300c + {0.852539f, 0.169434f, 0.859863f, 0.178711f, 1.0000f, -16.6250f, 30.0000f, 15, 19}, // 300d + {0.615234f, 0.025879f, 0.623047f, 0.035156f, 14.7500f, -29.0625f, 30.0000f, 16, 19}, // 300e + {0.529297f, 0.313477f, 0.537109f, 0.322754f, 0.0625f, -16.6875f, 30.0000f, 16, 19}, // 300f + {0.993164f, 0.416016f, 0.999512f, 0.431641f, 16.3125f, -29.1250f, 30.0000f, 13, 32}, // 3010 + {0.148926f, 0.906250f, 0.155273f, 0.921875f, 1.0000f, -29.1250f, 30.0000f, 13, 32}, // 3011 + {0.846680f, 0.824707f, 0.858398f, 0.837891f, 3.1250f, -26.0625f, 30.0000f, 24, 27}, // 3012 + {0.787598f, 0.816895f, 0.800293f, 0.829590f, 2.3125f, -26.5000f, 30.0000f, 26, 26}, // 3013 + {0.741699f, 0.907715f, 0.748047f, 0.923340f, 16.7500f, -29.3750f, 30.0000f, 13, 32}, // 3014 + {0.840820f, 0.907715f, 0.847168f, 0.923340f, 1.0000f, -29.3750f, 30.0000f, 13, 32}, // 3015 + {0.992188f, 0.891602f, 0.999512f, 0.907227f, 15.0625f, -29.3750f, 30.0000f, 15, 32}, // 3016 + {0.000000f, 0.892090f, 0.007324f, 0.907715f, 0.0000f, -29.3750f, 30.0000f, 15, 32}, // 3017 + {0.828125f, 0.744141f, 0.833496f, 0.759766f, 17.4375f, -29.0625f, 30.0000f, 11, 32}, // 3018 + {0.823242f, 0.916016f, 0.828613f, 0.931641f, 1.6875f, -29.0625f, 30.0000f, 11, 32}, // 3019 + {0.903320f, 0.907715f, 0.909668f, 0.923340f, 15.3125f, -28.6250f, 30.0000f, 13, 32}, // 301a + {0.950684f, 0.907715f, 0.957031f, 0.923340f, 1.6250f, -28.6250f, 30.0000f, 13, 32}, // 301b + {0.405762f, 0.919922f, 0.421387f, 0.924805f, -0.8750f, -18.0000f, 30.0000f, 32, 10}, // 301c + {0.786621f, 0.257324f, 0.794434f, 0.264160f, 14.0000f, -29.6250f, 30.0000f, 16, 14}, // 301d + {0.160156f, 0.070313f, 0.167480f, 0.077148f, 1.0000f, -29.6250f, 30.0000f, 15, 14}, // 301e + {0.337891f, 0.257813f, 0.345703f, 0.264648f, 3.3750f, -12.3125f, 30.0000f, 16, 14}, // 301f + {0.015137f, 0.522949f, 0.029297f, 0.534180f, 0.6875f, -24.6875f, 30.0000f, 29, 23}, // 3020 + {0.817383f, 0.355957f, 0.820801f, 0.368164f, 11.3125f, -25.5000f, 30.0000f, 7, 25}, // 3021 + {0.802734f, 0.026367f, 0.809570f, 0.038086f, 8.1250f, -25.4375f, 30.0000f, 14, 24}, // 3022 + {0.283203f, 0.894043f, 0.292480f, 0.906250f, 5.6250f, -25.5000f, 30.0000f, 19, 25}, // 3023 + {0.988281f, 0.481445f, 0.999512f, 0.493652f, 2.5625f, -25.2500f, 30.0000f, 23, 25}, // 3024 + {0.328613f, 0.899414f, 0.337402f, 0.912109f, 6.5625f, -26.4375f, 30.0000f, 18, 26}, // 3025 + {0.806641f, 0.054199f, 0.818359f, 0.062500f, 3.5000f, -24.1250f, 30.0000f, 24, 17}, // 3026 + {0.652832f, 0.893555f, 0.664551f, 0.903320f, 3.5000f, -24.7500f, 30.0000f, 24, 20}, // 3027 + {0.511719f, 0.862305f, 0.523438f, 0.873535f, 3.4375f, -25.2500f, 30.0000f, 24, 23}, // 3028 + {0.106934f, 0.833984f, 0.118652f, 0.846680f, 4.1250f, -26.3125f, 30.0000f, 24, 26}, // 3029 + {0.530762f, 0.177734f, 0.536621f, 0.183594f, 1.3125f, -11.9375f, 30.0000f, 12, 12}, // 302a + {0.579590f, 0.196777f, 0.585449f, 0.202637f, 1.3125f, -27.3125f, 30.0000f, 12, 12}, // 302b + {0.573730f, 0.212402f, 0.579590f, 0.218262f, 16.7500f, -27.3125f, 30.0000f, 12, 12}, // 302c + {0.346191f, 0.257813f, 0.352051f, 0.263672f, 16.7500f, -11.9375f, 30.0000f, 12, 12}, // 302d + {0.703613f, 0.486816f, 0.708008f, 0.491211f, 0.5625f, -17.8750f, 30.0000f, 9, 9}, // 302e + {0.864746f, 0.064941f, 0.869141f, 0.072266f, 0.5000f, -20.9375f, 30.0000f, 9, 15}, // 302f + {0.145020f, 0.086426f, 0.159668f, 0.091309f, 0.0000f, -18.3750f, 30.0000f, 30, 10}, // 3030 + {0.247559f, 0.862305f, 0.256348f, 0.877441f, 6.5000f, -28.3125f, 30.0000f, 18, 31}, // 3031 + {0.901367f, 0.734863f, 0.913574f, 0.750000f, 4.0000f, -28.4375f, 30.0000f, 25, 31}, // 3032 + {0.456055f, 0.842773f, 0.466309f, 0.856934f, 3.1875f, -27.5000f, 30.0000f, 21, 29}, // 3033 + {0.548340f, 0.707031f, 0.562012f, 0.721191f, 1.8125f, -27.5000f, 30.0000f, 28, 29}, // 3034 + {0.537109f, 0.857910f, 0.546387f, 0.872559f, 4.9375f, -27.9375f, 30.0000f, 19, 30}, // 3035 + {0.914551f, 0.690918f, 0.928711f, 0.705078f, 1.1875f, -27.7500f, 30.0000f, 29, 29}, // 3036 + {0.262207f, 0.505859f, 0.276855f, 0.520996f, -0.1875f, -28.8750f, 30.0000f, 30, 31}, // 3037 + {0.013672f, 0.791504f, 0.026855f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3038 + {0.092773f, 0.791504f, 0.105957f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3039 + {0.299805f, 0.791504f, 0.312988f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303a + {0.748535f, 0.791504f, 0.761719f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303b + {0.762207f, 0.791504f, 0.775391f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303c + {0.928223f, 0.791504f, 0.941406f, 0.804688f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303d + {0.648926f, 0.791992f, 0.662109f, 0.805176f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 303e + {0.989746f, 0.083984f, 0.999512f, 0.099609f, 5.1875f, -29.0625f, 30.0000f, 20, 32}, // 303f +// RANGE: 0x3041 - 0x3098, start 0x4ce + {0.629395f, 0.852051f, 0.640625f, 0.864258f, 3.5625f, -25.6250f, 30.0000f, 23, 25}, // 3041 + {0.434082f, 0.714355f, 0.447266f, 0.729004f, 1.3750f, -27.4375f, 30.0000f, 27, 30}, // 3042 + {0.693848f, 0.778320f, 0.704590f, 0.789551f, 4.5000f, -24.1250f, 30.0000f, 22, 23}, // 3043 + {0.577637f, 0.803711f, 0.590332f, 0.817383f, 2.3125f, -26.8125f, 30.0000f, 26, 28}, // 3044 + {0.393066f, 0.120605f, 0.403320f, 0.132324f, 3.6875f, -24.6875f, 30.0000f, 21, 24}, // 3045 + {0.435059f, 0.811035f, 0.447266f, 0.824707f, 1.3750f, -26.7500f, 30.0000f, 25, 28}, // 3046 + {0.790527f, 0.042480f, 0.802246f, 0.054199f, 3.0000f, -25.3125f, 30.0000f, 24, 24}, // 3047 + {0.390625f, 0.707520f, 0.404297f, 0.721680f, 0.6875f, -27.6250f, 30.0000f, 28, 29}, // 3048 + {0.384766f, 0.342773f, 0.395996f, 0.354492f, 3.5625f, -25.1250f, 30.0000f, 23, 24}, // 3049 + {0.187500f, 0.728516f, 0.200684f, 0.742676f, 1.0625f, -27.9375f, 30.0000f, 27, 29}, // 304a + {0.985840f, 0.622070f, 0.999512f, 0.636719f, 0.3750f, -28.1875f, 30.0000f, 28, 30}, // 304b + {0.233398f, 0.506836f, 0.248535f, 0.521484f, -0.2500f, -28.4375f, 30.0000f, 31, 30}, // 304c + {0.964844f, 0.732422f, 0.977539f, 0.747070f, 0.9375f, -28.3750f, 30.0000f, 26, 30}, // 304d + {0.875488f, 0.604492f, 0.890137f, 0.619141f, 1.0000f, -29.0000f, 30.0000f, 30, 30}, // 304e + {0.659180f, 0.825684f, 0.670410f, 0.839355f, 2.3125f, -27.3125f, 30.0000f, 23, 28}, // 304f + {0.074707f, 0.689453f, 0.088379f, 0.704102f, 2.3125f, -28.6250f, 30.0000f, 28, 30}, // 3050 + {0.562500f, 0.714355f, 0.575684f, 0.729004f, 2.8125f, -27.5000f, 30.0000f, 27, 30}, // 3051 + {0.394531f, 0.432617f, 0.409180f, 0.448242f, 0.8750f, -29.1875f, 30.0000f, 30, 32}, // 3052 + {0.861816f, 0.822754f, 0.874023f, 0.835449f, 2.8750f, -25.5000f, 30.0000f, 25, 26}, // 3053 + {0.081055f, 0.747559f, 0.094238f, 0.761230f, 1.4375f, -28.2500f, 30.0000f, 27, 28}, // 3054 + {0.062012f, 0.750977f, 0.074707f, 0.765137f, 0.8750f, -27.6875f, 30.0000f, 26, 29}, // 3055 + {0.346191f, 0.667969f, 0.360352f, 0.682617f, 0.7500f, -28.6250f, 30.0000f, 29, 30}, // 3056 + {0.309082f, 0.818848f, 0.320801f, 0.832520f, 4.1875f, -27.1250f, 30.0000f, 24, 28}, // 3057 + {0.517578f, 0.733398f, 0.530273f, 0.748047f, 3.5000f, -28.6250f, 30.0000f, 26, 30}, // 3058 + {0.000000f, 0.694336f, 0.013672f, 0.708984f, 1.4375f, -27.1875f, 30.0000f, 28, 30}, // 3059 + {0.179199f, 0.206055f, 0.193359f, 0.221680f, 0.6250f, -29.8750f, 30.0000f, 29, 32}, // 305a + {0.248535f, 0.523438f, 0.262207f, 0.537109f, 0.9375f, -26.8125f, 30.0000f, 28, 28}, // 305b + {0.868164f, 0.371582f, 0.883301f, 0.386719f, 0.1250f, -29.9375f, 30.0000f, 31, 31}, // 305c + {0.872559f, 0.724609f, 0.886230f, 0.738281f, 1.0625f, -26.5625f, 30.0000f, 28, 28}, // 305d + {0.305176f, 0.605957f, 0.319824f, 0.620605f, 0.3750f, -28.2500f, 30.0000f, 30, 30}, // 305e + {0.233887f, 0.728516f, 0.247070f, 0.742676f, 1.5625f, -27.9375f, 30.0000f, 27, 29}, // 305f + {0.144531f, 0.691406f, 0.158691f, 0.705566f, 0.6250f, -28.2500f, 30.0000f, 29, 29}, // 3060 + {0.247070f, 0.750977f, 0.259766f, 0.765137f, 2.2500f, -28.0000f, 30.0000f, 26, 29}, // 3061 + {0.074219f, 0.673828f, 0.087891f, 0.688965f, 1.2500f, -29.8125f, 30.0000f, 28, 31}, // 3062 + {0.516602f, 0.193848f, 0.527344f, 0.203125f, 3.1875f, -22.1250f, 30.0000f, 22, 19}, // 3063 + {0.502930f, 0.846680f, 0.516113f, 0.857422f, 1.6250f, -23.3750f, 30.0000f, 27, 22}, // 3064 + {0.204102f, 0.708008f, 0.217773f, 0.722168f, 0.8750f, -30.1875f, 30.0000f, 28, 29}, // 3065 + {0.959961f, 0.747559f, 0.973633f, 0.760742f, 0.6250f, -25.6250f, 30.0000f, 28, 27}, // 3066 + {0.308594f, 0.728516f, 0.322754f, 0.741699f, 0.6250f, -25.6250f, 30.0000f, 29, 27}, // 3067 + {0.432617f, 0.825195f, 0.444336f, 0.838379f, 2.8750f, -27.3125f, 30.0000f, 24, 27}, // 3068 + {0.410156f, 0.728516f, 0.423340f, 0.742676f, 2.8750f, -28.3750f, 30.0000f, 27, 29}, // 3069 + {0.159180f, 0.691406f, 0.173340f, 0.705566f, 0.3750f, -28.0000f, 30.0000f, 29, 29}, // 306a + {0.121582f, 0.748047f, 0.134766f, 0.761719f, 1.8750f, -27.4375f, 30.0000f, 27, 28}, // 306b + {0.252441f, 0.708008f, 0.266602f, 0.721680f, 1.1250f, -27.5000f, 30.0000f, 29, 28}, // 306c + {0.404785f, 0.708008f, 0.418945f, 0.721680f, 0.6250f, -27.2500f, 30.0000f, 29, 28}, // 306d + {0.192383f, 0.269043f, 0.205566f, 0.281738f, 1.4375f, -25.4375f, 30.0000f, 27, 26}, // 306e + {0.660156f, 0.708008f, 0.673828f, 0.722168f, 1.3125f, -27.2500f, 30.0000f, 28, 29}, // 306f + {0.713867f, 0.506836f, 0.728516f, 0.521973f, 0.5000f, -29.2500f, 30.0000f, 30, 31}, // 3070 + {0.014160f, 0.507324f, 0.028809f, 0.522461f, 0.8125f, -29.3125f, 30.0000f, 30, 31}, // 3071 + {0.767090f, 0.728516f, 0.781250f, 0.741699f, 1.6250f, -26.3125f, 30.0000f, 29, 27}, // 3072 + {0.800293f, 0.667969f, 0.814453f, 0.682617f, 0.6250f, -29.2500f, 30.0000f, 29, 30}, // 3073 + {0.935547f, 0.101074f, 0.949707f, 0.116211f, 1.0625f, -29.8750f, 30.0000f, 29, 31}, // 3074 + {0.175293f, 0.348145f, 0.189941f, 0.361328f, 0.1875f, -26.7500f, 30.0000f, 30, 27}, // 3075 + {0.351563f, 0.605957f, 0.366211f, 0.620605f, -0.1250f, -29.2500f, 30.0000f, 30, 30}, // 3076 + {0.833496f, 0.372070f, 0.848633f, 0.387207f, -0.5625f, -29.8750f, 30.0000f, 31, 31}, // 3077 + {0.354004f, 0.264648f, 0.368164f, 0.275391f, 0.5625f, -23.8750f, 30.0000f, 29, 22}, // 3078 + {0.589844f, 0.729004f, 0.604004f, 0.742188f, 0.5625f, -28.1875f, 30.0000f, 29, 27}, // 3079 + {0.423828f, 0.729492f, 0.437988f, 0.742676f, -0.0625f, -28.8750f, 30.0000f, 29, 27}, // 307a + {0.852051f, 0.725586f, 0.865723f, 0.739258f, 1.2500f, -27.1875f, 30.0000f, 28, 28}, // 307b + {0.829590f, 0.605957f, 0.844238f, 0.620605f, 0.3125f, -28.7500f, 30.0000f, 30, 30}, // 307c + {0.665527f, 0.606445f, 0.680176f, 0.621094f, 0.8125f, -28.8750f, 30.0000f, 30, 30}, // 307d + {0.000000f, 0.709473f, 0.013672f, 0.723633f, 1.7500f, -27.9375f, 30.0000f, 28, 29}, // 307e + {0.674316f, 0.709961f, 0.687988f, 0.724121f, 1.4375f, -27.1875f, 30.0000f, 28, 29}, // 307f + {0.843750f, 0.709961f, 0.857422f, 0.724121f, 1.6250f, -27.6875f, 30.0000f, 28, 29}, // 3080 + {0.560059f, 0.729492f, 0.573242f, 0.743652f, 1.8750f, -27.9375f, 30.0000f, 27, 29}, // 3081 + {0.135254f, 0.748047f, 0.148438f, 0.761719f, 1.3125f, -27.6875f, 30.0000f, 27, 28}, // 3082 + {0.583008f, 0.778320f, 0.594238f, 0.790039f, 3.1250f, -25.3125f, 30.0000f, 23, 24}, // 3083 + {0.872559f, 0.709961f, 0.886230f, 0.724121f, 0.9375f, -27.6875f, 30.0000f, 28, 29}, // 3084 + {0.755859f, 0.863770f, 0.766602f, 0.875977f, 4.0625f, -25.3750f, 30.0000f, 22, 25}, // 3085 + {0.644531f, 0.714355f, 0.657715f, 0.729004f, 2.0000f, -27.7500f, 30.0000f, 27, 30}, // 3086 + {0.940430f, 0.604004f, 0.951660f, 0.615234f, 3.7500f, -25.0000f, 30.0000f, 23, 23}, // 3087 + {0.676270f, 0.791992f, 0.689453f, 0.805176f, 1.5000f, -27.4375f, 30.0000f, 27, 27}, // 3088 + {0.470703f, 0.811035f, 0.482910f, 0.824707f, 2.3125f, -27.4375f, 30.0000f, 25, 28}, // 3089 + {0.243164f, 0.820313f, 0.253906f, 0.834961f, 3.8125f, -27.1250f, 30.0000f, 22, 30}, // 308a + {0.813965f, 0.791992f, 0.827148f, 0.805176f, 0.4375f, -27.0000f, 30.0000f, 27, 27}, // 308b + {0.375488f, 0.691406f, 0.389648f, 0.705566f, 1.1250f, -27.2500f, 30.0000f, 29, 29}, // 308c + {0.512695f, 0.748535f, 0.525879f, 0.762207f, 1.0000f, -26.8125f, 30.0000f, 27, 28}, // 308d + {0.987305f, 0.249023f, 0.999023f, 0.260742f, 2.7500f, -25.0625f, 30.0000f, 24, 24}, // 308e + {0.339355f, 0.726563f, 0.353027f, 0.740234f, 0.3750f, -27.5000f, 30.0000f, 28, 28}, // 308f + {0.866211f, 0.791992f, 0.879395f, 0.805176f, 1.5625f, -26.3750f, 30.0000f, 27, 27}, // 3090 + {0.942871f, 0.709961f, 0.957031f, 0.723633f, 0.5625f, -27.2500f, 30.0000f, 29, 28}, // 3091 + {0.635254f, 0.729492f, 0.648438f, 0.743652f, 1.4375f, -28.1875f, 30.0000f, 27, 29}, // 3092 + {0.857910f, 0.711426f, 0.872070f, 0.725098f, 0.6875f, -27.3750f, 30.0000f, 29, 28}, // 3093 + {0.814941f, 0.667969f, 0.829590f, 0.682129f, 1.0625f, -27.6250f, 30.0000f, 30, 29}, // 3094 + {0.146973f, 0.792480f, 0.160156f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3095 + {0.160645f, 0.792480f, 0.173828f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3096 + {0.215332f, 0.792480f, 0.228516f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 3097 +// RANGE: 0x3099 - 0x30a0, start 0x525 + {0.139648f, 0.199219f, 0.145020f, 0.204590f, 17.1875f, -28.2500f, 30.0000f, 11, 11}, // 3099 + {0.557617f, 0.203125f, 0.562988f, 0.208496f, 19.0625f, -29.8750f, 30.0000f, 11, 11}, // 309a + {0.120605f, 0.245605f, 0.125977f, 0.250977f, 13.0625f, -28.2500f, 30.0000f, 11, 11}, // 309b + {0.506348f, 0.304199f, 0.511719f, 0.309570f, 12.6875f, -29.8750f, 30.0000f, 11, 11}, // 309c + {0.146484f, 0.833984f, 0.158203f, 0.846680f, 2.5625f, -26.3750f, 30.0000f, 24, 26}, // 309d + {0.292969f, 0.823242f, 0.305176f, 0.835938f, 2.5625f, -26.3750f, 30.0000f, 25, 26}, // 309e + {0.229004f, 0.792480f, 0.242188f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 309f +// RANGE: 0x30a0 - 0x3100, start 0x52c + {0.326660f, 0.792480f, 0.339844f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 30a0 + {0.038574f, 0.875000f, 0.049805f, 0.886230f, 3.9375f, -23.9375f, 30.0000f, 23, 23}, // 30a1 + {0.929199f, 0.691406f, 0.943359f, 0.705566f, 0.8125f, -26.5625f, 30.0000f, 29, 29}, // 30a2 + {0.105957f, 0.777832f, 0.116211f, 0.789551f, 4.5000f, -25.1250f, 30.0000f, 21, 24}, // 30a3 + {0.704102f, 0.733398f, 0.716797f, 0.748047f, 1.6250f, -28.0000f, 30.0000f, 26, 30}, // 30a4 + {0.561523f, 0.887695f, 0.571777f, 0.899414f, 4.7500f, -24.8750f, 30.0000f, 21, 24}, // 30a5 + {0.827148f, 0.714355f, 0.840332f, 0.729004f, 1.7500f, -28.1250f, 30.0000f, 27, 30}, // 30a6 + {0.698730f, 0.680176f, 0.709961f, 0.690430f, 3.6250f, -22.8750f, 30.0000f, 23, 21}, // 30a7 + {0.886719f, 0.714355f, 0.901367f, 0.727539f, 0.3750f, -26.0625f, 30.0000f, 30, 27}, // 30a8 + {0.564453f, 0.862305f, 0.576172f, 0.873535f, 3.5000f, -24.5625f, 30.0000f, 24, 23}, // 30a9 + {0.970215f, 0.606445f, 0.984863f, 0.621094f, 0.8750f, -27.6875f, 30.0000f, 30, 30}, // 30aa + {0.678223f, 0.694824f, 0.691895f, 0.709473f, 0.5625f, -27.8750f, 30.0000f, 28, 30}, // 30ab + {0.257324f, 0.240234f, 0.271484f, 0.255371f, 0.5625f, -28.9375f, 30.0000f, 29, 31}, // 30ac + {0.653809f, 0.668457f, 0.667969f, 0.683105f, 0.1875f, -28.1250f, 30.0000f, 29, 30}, // 30ad + {0.217773f, 0.507324f, 0.232422f, 0.522461f, 0.0625f, -28.6250f, 30.0000f, 30, 31}, // 30ae + {0.957520f, 0.714355f, 0.970703f, 0.729004f, 1.5625f, -28.4375f, 30.0000f, 27, 30}, // 30af + {0.409668f, 0.432617f, 0.424316f, 0.448242f, 0.3125f, -29.5000f, 30.0000f, 30, 32}, // 30b0 + {0.584961f, 0.606934f, 0.599609f, 0.621582f, -0.1250f, -28.4375f, 30.0000f, 30, 30}, // 30b1 + {0.407227f, 0.507324f, 0.421875f, 0.522461f, -0.1250f, -29.1250f, 30.0000f, 30, 31}, // 30b2 + {0.395996f, 0.792480f, 0.409180f, 0.805664f, 0.8750f, -26.0625f, 30.0000f, 27, 27}, // 30b3 + {0.985352f, 0.324707f, 0.999512f, 0.340332f, 0.4375f, -30.3125f, 30.0000f, 29, 32}, // 30b4 + {0.830078f, 0.668457f, 0.844238f, 0.683105f, 0.5000f, -27.6250f, 30.0000f, 29, 30}, // 30b5 + {0.507813f, 0.432617f, 0.523438f, 0.447266f, -0.1250f, -28.0000f, 30.0000f, 32, 30}, // 30b6 + {0.359863f, 0.692383f, 0.374023f, 0.706543f, 0.4375f, -27.6875f, 30.0000f, 29, 29}, // 30b7 + {0.978027f, 0.668457f, 0.992188f, 0.683105f, 0.3125f, -28.0000f, 30.0000f, 29, 30}, // 30b8 + {0.344238f, 0.683105f, 0.359375f, 0.696777f, 0.4375f, -25.8750f, 30.0000f, 31, 28}, // 30b9 + {0.984375f, 0.051758f, 0.999512f, 0.067383f, -0.3750f, -30.0625f, 30.0000f, 31, 32}, // 30ba + {0.341309f, 0.712402f, 0.355469f, 0.726074f, 0.5625f, -27.6250f, 30.0000f, 29, 28}, // 30bb + {0.550781f, 0.692383f, 0.564941f, 0.706543f, 0.4375f, -28.0625f, 30.0000f, 29, 29}, // 30bc + {0.382324f, 0.750977f, 0.395020f, 0.765137f, 1.9375f, -27.4375f, 30.0000f, 26, 29}, // 30bd + {0.144043f, 0.253418f, 0.157227f, 0.268555f, 1.8750f, -28.9375f, 30.0000f, 27, 31}, // 30be + {0.323242f, 0.733887f, 0.335938f, 0.748535f, 1.5625f, -28.1875f, 30.0000f, 26, 30}, // 30bf + {0.879395f, 0.432617f, 0.894043f, 0.448242f, -0.2500f, -29.8125f, 30.0000f, 30, 32}, // 30c0 + {0.422363f, 0.507324f, 0.437012f, 0.522461f, 0.5625f, -28.4375f, 30.0000f, 30, 31}, // 30c1 + {0.694336f, 0.507324f, 0.708984f, 0.522461f, 0.3125f, -28.4375f, 30.0000f, 30, 31}, // 30c2 + {0.101563f, 0.892090f, 0.111816f, 0.903320f, 3.6250f, -23.9375f, 30.0000f, 21, 23}, // 30c3 + {0.819824f, 0.729492f, 0.833008f, 0.743652f, 0.6250f, -27.2500f, 30.0000f, 27, 29}, // 30c4 + {0.590820f, 0.673828f, 0.604492f, 0.688965f, 1.0000f, -28.8750f, 30.0000f, 28, 31}, // 30c5 + {0.240234f, 0.668945f, 0.254883f, 0.683105f, 0.1875f, -26.2500f, 30.0000f, 30, 29}, // 30c6 + {0.165039f, 0.632813f, 0.180176f, 0.646973f, 0.1875f, -26.7500f, 30.0000f, 31, 29}, // 30c7 + {0.011230f, 0.843262f, 0.021484f, 0.857422f, 6.6875f, -27.6250f, 30.0000f, 21, 29}, // 30c8 + {0.588867f, 0.831543f, 0.599121f, 0.846191f, 7.7500f, -27.7500f, 30.0000f, 21, 30}, // 30c9 + {0.314941f, 0.668945f, 0.329102f, 0.683594f, 0.4375f, -27.6250f, 30.0000f, 29, 30}, // 30ca + {0.360840f, 0.752930f, 0.375488f, 0.765137f, 0.3125f, -25.3750f, 30.0000f, 30, 25}, // 30cb + {0.617676f, 0.748535f, 0.630859f, 0.762207f, 1.4375f, -26.0625f, 30.0000f, 27, 28}, // 30cc + {0.844727f, 0.606934f, 0.859375f, 0.621582f, -0.0625f, -27.6250f, 30.0000f, 30, 30}, // 30cd + {0.590820f, 0.803711f, 0.603516f, 0.817383f, 1.8750f, -26.2500f, 30.0000f, 26, 28}, // 30ce + {0.422363f, 0.668945f, 0.437012f, 0.683105f, 0.1250f, -27.7500f, 30.0000f, 30, 29}, // 30cf + {0.710938f, 0.632813f, 0.726074f, 0.646973f, -0.6250f, -28.0000f, 30.0000f, 31, 29}, // 30d0 + {0.095703f, 0.372559f, 0.110840f, 0.387695f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 30d1 + {0.604004f, 0.803711f, 0.616699f, 0.817383f, 2.8750f, -27.1250f, 30.0000f, 26, 28}, // 30d2 + {0.812988f, 0.712402f, 0.826660f, 0.726563f, 2.4375f, -28.0000f, 30.0000f, 28, 29}, // 30d3 + {0.390137f, 0.692871f, 0.404297f, 0.707031f, 2.0625f, -28.0000f, 30.0000f, 29, 29}, // 30d4 + {0.703613f, 0.803711f, 0.716309f, 0.817383f, 2.5000f, -26.0000f, 30.0000f, 26, 28}, // 30d5 + {0.755371f, 0.503418f, 0.769531f, 0.519531f, 1.1875f, -30.6250f, 30.0000f, 29, 33}, // 30d6 + {0.177246f, 0.093750f, 0.192383f, 0.109375f, 0.6250f, -29.7500f, 30.0000f, 31, 32}, // 30d7 + {0.211914f, 0.806152f, 0.227051f, 0.817383f, -0.3125f, -23.5625f, 30.0000f, 31, 23}, // 30d8 + {0.370605f, 0.152832f, 0.385742f, 0.164551f, -0.3125f, -24.5625f, 30.0000f, 31, 24}, // 30d9 + {0.844238f, 0.757324f, 0.859375f, 0.769043f, -0.3125f, -24.5625f, 30.0000f, 31, 24}, // 30da + {0.437500f, 0.668945f, 0.452148f, 0.683105f, 0.0625f, -27.5625f, 30.0000f, 30, 29}, // 30db + {0.859863f, 0.607422f, 0.874512f, 0.622070f, 0.0625f, -28.6250f, 30.0000f, 30, 30}, // 30dc + {0.729004f, 0.507324f, 0.743652f, 0.522461f, 0.0625f, -29.5000f, 30.0000f, 30, 31}, // 30dd + {0.704102f, 0.748535f, 0.717773f, 0.761719f, 1.3750f, -25.8750f, 30.0000f, 28, 27}, // 30de + {0.296387f, 0.712891f, 0.310059f, 0.727051f, 1.0625f, -27.1250f, 30.0000f, 28, 29}, // 30df + {0.575684f, 0.668945f, 0.590332f, 0.683105f, 0.3750f, -27.8125f, 30.0000f, 30, 29}, // 30e0 + {0.441406f, 0.751465f, 0.454102f, 0.765625f, 1.1875f, -27.6250f, 30.0000f, 26, 29}, // 30e1 + {0.187012f, 0.714844f, 0.201660f, 0.728027f, 0.4375f, -26.1875f, 30.0000f, 30, 27}, // 30e2 + {0.759277f, 0.520020f, 0.770020f, 0.531738f, 4.0625f, -24.6250f, 30.0000f, 22, 24}, // 30e3 + {0.844238f, 0.694824f, 0.857910f, 0.709473f, 1.0625f, -28.0625f, 30.0000f, 28, 30}, // 30e4 + {0.134766f, 0.892090f, 0.145996f, 0.902344f, 3.3750f, -23.1250f, 30.0000f, 23, 21}, // 30e5 + {0.310547f, 0.714844f, 0.325195f, 0.728027f, 0.2500f, -25.9375f, 30.0000f, 30, 27}, // 30e6 + {0.692383f, 0.905273f, 0.702637f, 0.915527f, 4.1250f, -23.1875f, 30.0000f, 21, 21}, // 30e7 + {0.409668f, 0.792480f, 0.422852f, 0.805664f, 1.1250f, -25.9375f, 30.0000f, 27, 27}, // 30e8 + {0.984863f, 0.712891f, 0.998535f, 0.727051f, 1.0625f, -26.5000f, 30.0000f, 28, 29}, // 30e9 + {0.480957f, 0.831055f, 0.491699f, 0.845215f, 4.3750f, -27.0625f, 30.0000f, 22, 29}, // 30ea + {0.437500f, 0.508301f, 0.452637f, 0.522949f, -0.1875f, -27.6875f, 30.0000f, 31, 30}, // 30eb + {0.969238f, 0.804688f, 0.981445f, 0.818848f, 4.0625f, -27.6875f, 30.0000f, 25, 29}, // 30ec + {0.349121f, 0.806641f, 0.361816f, 0.819824f, 2.0000f, -25.9375f, 30.0000f, 26, 27}, // 30ed + {0.758789f, 0.901855f, 0.769043f, 0.912598f, 4.7500f, -23.0625f, 30.0000f, 21, 22}, // 30ee + {0.718262f, 0.748535f, 0.731445f, 0.762207f, 1.6875f, -25.9375f, 30.0000f, 27, 28}, // 30ef + {0.910156f, 0.668945f, 0.924805f, 0.683105f, 0.5000f, -27.5000f, 30.0000f, 30, 29}, // 30f0 + {0.593262f, 0.715332f, 0.607910f, 0.728516f, 0.2500f, -25.9375f, 30.0000f, 30, 27}, // 30f1 + {0.951172f, 0.729492f, 0.964355f, 0.743652f, 1.6250f, -26.6250f, 30.0000f, 27, 29}, // 30f2 + {0.805664f, 0.727051f, 0.819336f, 0.740723f, 1.1875f, -26.6250f, 30.0000f, 28, 28}, // 30f3 + {0.300781f, 0.682129f, 0.314453f, 0.697266f, 1.1875f, -29.1875f, 30.0000f, 28, 31}, // 30f4 + {0.125977f, 0.875000f, 0.136719f, 0.886719f, 3.9375f, -24.7500f, 30.0000f, 22, 24}, // 30f5 + {0.624023f, 0.790039f, 0.635254f, 0.801758f, 3.3750f, -24.8750f, 30.0000f, 23, 24}, // 30f6 + {0.500488f, 0.509277f, 0.515137f, 0.524414f, 0.7500f, -29.0625f, 30.0000f, 30, 31}, // 30f7 + {0.901367f, 0.372559f, 0.916504f, 0.387695f, 0.1875f, -29.3125f, 30.0000f, 31, 31}, // 30f8 + {0.351074f, 0.373047f, 0.366211f, 0.388184f, 0.4375f, -29.8750f, 30.0000f, 31, 31}, // 30f9 + {0.910156f, 0.432617f, 0.924805f, 0.448242f, 1.1875f, -29.4375f, 30.0000f, 30, 32}, // 30fa + {0.802734f, 0.488770f, 0.807129f, 0.493164f, 2.8125f, -17.8750f, 30.0000f, 9, 9}, // 30fb + {0.257813f, 0.122559f, 0.272461f, 0.125977f, 0.4375f, -16.9375f, 30.0000f, 30, 7}, // 30fc + {0.629395f, 0.894531f, 0.638672f, 0.906738f, 6.1250f, -24.0000f, 30.0000f, 19, 25}, // 30fd + {0.676758f, 0.857910f, 0.686035f, 0.872559f, 6.1250f, -28.2500f, 30.0000f, 19, 30}, // 30fe + {0.461426f, 0.792480f, 0.474609f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 30ff +// RANGE: 0x31f0 - 0x3200, start 0x58c + {0.563965f, 0.792480f, 0.577148f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f0 + {0.879883f, 0.792480f, 0.893066f, 0.805664f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f1 + {0.051758f, 0.792969f, 0.064941f, 0.806152f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f2 + {0.242676f, 0.792969f, 0.255859f, 0.806152f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f3 + {0.340332f, 0.792969f, 0.353516f, 0.806152f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f4 + {0.354004f, 0.792969f, 0.367188f, 0.806152f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f5 + {0.367676f, 0.792969f, 0.380859f, 0.806152f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f6 + {0.423340f, 0.793457f, 0.436523f, 0.806641f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f7 + {0.852051f, 0.793457f, 0.865234f, 0.806641f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f8 + {0.533691f, 0.794434f, 0.546875f, 0.807617f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31f9 + {0.827637f, 0.796875f, 0.840820f, 0.810059f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fa + {0.198242f, 0.797363f, 0.211426f, 0.810547f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fb + {0.285156f, 0.797363f, 0.298340f, 0.810547f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fc + {0.437012f, 0.797363f, 0.450195f, 0.810547f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fd + {0.475098f, 0.797363f, 0.488281f, 0.810547f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31fe + {0.510254f, 0.797363f, 0.523438f, 0.810547f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // 31ff +// RANGE: 0x4e00 - 0xa000, start 0x59c + {0.241211f, 0.234863f, 0.254883f, 0.238281f, 1.6250f, -17.1875f, 30.0000f, 28, 7}, // 4e00 + {0.772461f, 0.669434f, 0.786621f, 0.684082f, 0.9375f, -27.0625f, 30.0000f, 29, 30}, // 4e01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e02 - {0.088379f, 0.640137f, 0.102539f, 0.654785f, 0.2500f, -28.6875f, 30.0000f, 29, 30}, // 4e03 + {0.271484f, 0.669922f, 0.285645f, 0.684570f, 0.2500f, -28.6875f, 30.0000f, 29, 30}, // 4e03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e06 - {0.951172f, 0.602539f, 0.966309f, 0.616699f, -0.1250f, -26.1875f, 30.0000f, 31, 29}, // 4e07 - {0.859863f, 0.413086f, 0.874512f, 0.428711f, 0.5000f, -28.8125f, 30.0000f, 30, 32}, // 4e08 - {0.503418f, 0.746582f, 0.517578f, 0.758789f, 0.9375f, -25.3750f, 30.0000f, 29, 25}, // 4e09 - {0.103027f, 0.640137f, 0.117676f, 0.654297f, 0.7500f, -28.5000f, 30.0000f, 30, 29}, // 4e0a - {0.378418f, 0.662109f, 0.392578f, 0.676270f, 0.5000f, -27.1875f, 30.0000f, 29, 29}, // 4e0b + {0.796875f, 0.633301f, 0.812012f, 0.647461f, -0.1250f, -26.1875f, 30.0000f, 31, 29}, // 4e07 + {0.378418f, 0.433105f, 0.393066f, 0.448730f, 0.5000f, -28.8125f, 30.0000f, 30, 32}, // 4e08 + {0.981934f, 0.804688f, 0.996094f, 0.816895f, 0.9375f, -25.3750f, 30.0000f, 29, 25}, // 4e09 + {0.604492f, 0.670898f, 0.619141f, 0.685059f, 0.7500f, -28.5000f, 30.0000f, 30, 29}, // 4e0a + {0.208008f, 0.693359f, 0.222168f, 0.707520f, 0.5000f, -27.1875f, 30.0000f, 29, 29}, // 4e0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e0c - {0.043945f, 0.581543f, 0.058594f, 0.596191f, 0.0625f, -27.0625f, 30.0000f, 30, 30}, // 4e0d - {0.000000f, 0.485352f, 0.014648f, 0.500488f, 0.0000f, -28.8125f, 30.0000f, 30, 31}, // 4e0e + {0.320313f, 0.607910f, 0.334961f, 0.622559f, 0.0625f, -27.0625f, 30.0000f, 30, 30}, // 4e0d + {0.802734f, 0.509277f, 0.817383f, 0.524414f, 0.0000f, -28.8125f, 30.0000f, 30, 31}, // 4e0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e13 - {0.258301f, 0.196777f, 0.272949f, 0.210449f, 0.5000f, -27.3125f, 30.0000f, 30, 28}, // 4e14 + {0.875000f, 0.695801f, 0.889648f, 0.709473f, 0.5000f, -27.3125f, 30.0000f, 30, 28}, // 4e14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e15 - {0.429199f, 0.351563f, 0.444336f, 0.366699f, -0.0625f, -28.1875f, 30.0000f, 31, 31}, // 4e16 + {0.621582f, 0.373535f, 0.636719f, 0.388672f, -0.0625f, -28.1875f, 30.0000f, 31, 31}, // 4e16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e17 - {0.787109f, 0.642090f, 0.801758f, 0.656250f, 0.2500f, -28.1250f, 30.0000f, 30, 29}, // 4e18 - {0.059082f, 0.581543f, 0.073730f, 0.596191f, 0.0000f, -27.0625f, 30.0000f, 30, 30}, // 4e19 - {0.147949f, 0.642578f, 0.162598f, 0.656738f, 0.0000f, -28.0000f, 30.0000f, 30, 29}, // 4e1a + {0.755371f, 0.670898f, 0.770020f, 0.685059f, 0.2500f, -28.1250f, 30.0000f, 30, 29}, // 4e18 + {0.274902f, 0.608398f, 0.289551f, 0.623047f, 0.0000f, -27.0625f, 30.0000f, 30, 30}, // 4e19 + {0.087891f, 0.671875f, 0.102539f, 0.686035f, 0.0000f, -28.0000f, 30.0000f, 30, 29}, // 4e1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e20 - {0.015137f, 0.487305f, 0.030273f, 0.501953f, -0.1875f, -27.6250f, 30.0000f, 31, 30}, // 4e21 + {0.833008f, 0.509277f, 0.848145f, 0.523926f, -0.1875f, -27.6250f, 30.0000f, 31, 30}, // 4e21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e25 - {0.045410f, 0.487305f, 0.060547f, 0.501953f, 0.0000f, -29.1875f, 30.0000f, 31, 30}, // 4e26 + {0.920410f, 0.509766f, 0.935547f, 0.524414f, 0.0000f, -29.1875f, 30.0000f, 31, 30}, // 4e26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e29 - {0.778320f, 0.032227f, 0.793945f, 0.047852f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 4e2a + {0.417480f, 0.051758f, 0.433105f, 0.067383f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 4e2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e2c - {0.014160f, 0.680176f, 0.026855f, 0.695313f, 1.9375f, -28.8125f, 30.0000f, 26, 31}, // 4e2d + {0.272461f, 0.303223f, 0.285156f, 0.318359f, 1.9375f, -28.8125f, 30.0000f, 26, 31}, // 4e2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e30 @@ -1178,10 +1479,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e37 - {0.577148f, 0.351563f, 0.592285f, 0.366699f, -0.4375f, -28.7500f, 30.0000f, 31, 31}, // 4e38 - {0.152344f, 0.581543f, 0.166992f, 0.596191f, 0.1875f, -27.3125f, 30.0000f, 30, 30}, // 4e39 - {0.864746f, 0.334961f, 0.877930f, 0.350098f, 0.4375f, -28.8750f, 30.0000f, 27, 31}, // 4e3a - {0.015137f, 0.583008f, 0.029785f, 0.597656f, 0.4375f, -29.2500f, 30.0000f, 30, 30}, // 4e3b + {0.366699f, 0.374023f, 0.381836f, 0.389160f, -0.4375f, -28.7500f, 30.0000f, 31, 31}, // 4e38 + {0.290039f, 0.608887f, 0.304688f, 0.623535f, 0.1875f, -27.3125f, 30.0000f, 30, 30}, // 4e39 + {0.885254f, 0.339844f, 0.898438f, 0.354980f, 0.4375f, -28.8750f, 30.0000f, 27, 31}, // 4e3a + {0.619629f, 0.608887f, 0.634277f, 0.623535f, 0.4375f, -29.2500f, 30.0000f, 30, 30}, // 4e3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e3e @@ -1191,17 +1492,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e44 - {0.754395f, 0.351563f, 0.769531f, 0.366699f, 0.5000f, -29.0625f, 30.0000f, 31, 31}, // 4e45 + {0.704102f, 0.374023f, 0.719238f, 0.389160f, 0.5000f, -29.0625f, 30.0000f, 31, 31}, // 4e45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e48 - {0.890137f, 0.177246f, 0.905762f, 0.192383f, -0.3750f, -28.5625f, 30.0000f, 32, 31}, // 4e49 + {0.742188f, 0.199219f, 0.757813f, 0.214355f, -0.3750f, -28.5625f, 30.0000f, 32, 31}, // 4e49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e4e - {0.770020f, 0.351563f, 0.785156f, 0.366699f, -0.0625f, -28.9375f, 30.0000f, 31, 31}, // 4e4f + {0.318848f, 0.375000f, 0.333984f, 0.390137f, -0.0625f, -28.9375f, 30.0000f, 31, 31}, // 4e4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e52 @@ -1209,13 +1510,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e56 - {0.794434f, 0.032227f, 0.810059f, 0.047852f, -0.5625f, -29.6250f, 30.0000f, 32, 32}, // 4e57 + {0.473145f, 0.051758f, 0.488770f, 0.067383f, -0.5625f, -29.6250f, 30.0000f, 32, 32}, // 4e57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e58 - {0.282227f, 0.737305f, 0.295410f, 0.750488f, 2.6875f, -26.2500f, 30.0000f, 27, 27}, // 4e59 + {0.662598f, 0.797363f, 0.675781f, 0.810547f, 2.6875f, -26.2500f, 30.0000f, 27, 27}, // 4e59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e5c - {0.925781f, 0.351563f, 0.940918f, 0.366699f, 0.3125f, -28.9375f, 30.0000f, 31, 31}, // 4e5d + {0.653809f, 0.375000f, 0.668945f, 0.390137f, 0.3125f, -28.9375f, 30.0000f, 31, 31}, // 4e5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e60 @@ -1234,10 +1535,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e6f - {0.279785f, 0.488281f, 0.294922f, 0.502930f, -0.8750f, -27.3750f, 30.0000f, 31, 30}, // 4e70 - {0.957520f, 0.351563f, 0.972656f, 0.366699f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 4e71 + {0.936035f, 0.509766f, 0.951172f, 0.524414f, -0.8750f, -27.3750f, 30.0000f, 31, 30}, // 4e70 + {0.786621f, 0.375977f, 0.801758f, 0.391113f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 4e71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e72 - {0.906250f, 0.177246f, 0.921875f, 0.192383f, -0.6250f, -28.4375f, 30.0000f, 32, 31}, // 4e73 + {0.387207f, 0.199707f, 0.402832f, 0.214844f, -0.6250f, -28.4375f, 30.0000f, 32, 31}, // 4e73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e76 @@ -1248,7 +1549,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e7d - {0.810547f, 0.032227f, 0.826172f, 0.047852f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 4e7e + {0.489258f, 0.051758f, 0.504883f, 0.067383f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 4e7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e81 @@ -1256,46 +1557,46 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e85 - {0.357422f, 0.750000f, 0.369141f, 0.764160f, 3.1250f, -27.1875f, 30.0000f, 24, 29}, // 4e86 + {0.834473f, 0.814941f, 0.846191f, 0.829102f, 3.1250f, -27.1875f, 30.0000f, 24, 29}, // 4e86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e87 - {0.256348f, 0.643066f, 0.270508f, 0.657715f, 0.7500f, -27.5000f, 30.0000f, 29, 30}, // 4e88 - {0.922363f, 0.177246f, 0.937500f, 0.192871f, 0.0625f, -28.9375f, 30.0000f, 31, 32}, // 4e89 + {0.286133f, 0.670898f, 0.300293f, 0.685547f, 0.7500f, -27.5000f, 30.0000f, 29, 30}, // 4e88 + {0.273926f, 0.128418f, 0.289063f, 0.144043f, 0.0625f, -28.9375f, 30.0000f, 31, 32}, // 4e89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e8a - {0.239258f, 0.352051f, 0.254395f, 0.367188f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 4e8b - {0.302246f, 0.773926f, 0.316406f, 0.784180f, 1.0000f, -23.7500f, 30.0000f, 29, 21}, // 4e8c + {0.507813f, 0.376465f, 0.522949f, 0.391602f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 4e8b + {0.096680f, 0.075684f, 0.110840f, 0.085938f, 1.0000f, -23.7500f, 30.0000f, 29, 21}, // 4e8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e8d - {0.802246f, 0.643066f, 0.816406f, 0.657715f, 0.6250f, -27.1875f, 30.0000f, 29, 30}, // 4e8e + {0.103027f, 0.671875f, 0.117188f, 0.686523f, 0.6250f, -27.1875f, 30.0000f, 29, 30}, // 4e8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e91 - {0.983887f, 0.662109f, 0.998535f, 0.675781f, 0.3125f, -27.2500f, 30.0000f, 30, 28}, // 4e92 + {0.943848f, 0.695801f, 0.958496f, 0.709473f, 0.3125f, -27.2500f, 30.0000f, 30, 28}, // 4e92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e93 - {0.727051f, 0.692871f, 0.741699f, 0.705566f, 0.4375f, -26.3125f, 30.0000f, 30, 26}, // 4e94 - {0.270996f, 0.352051f, 0.286133f, 0.367188f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 4e95 + {0.438477f, 0.733887f, 0.453125f, 0.746582f, 0.4375f, -26.3125f, 30.0000f, 30, 26}, // 4e94 + {0.637207f, 0.376465f, 0.652344f, 0.391602f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 4e95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e9b - {0.444336f, 0.603027f, 0.459473f, 0.617188f, -0.1250f, -27.5000f, 30.0000f, 31, 29}, // 4e9c + {0.905762f, 0.633301f, 0.920898f, 0.647461f, -0.1250f, -27.5000f, 30.0000f, 31, 29}, // 4e9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4e9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea0 - {0.871582f, 0.603027f, 0.886719f, 0.617188f, -0.0625f, -28.6875f, 30.0000f, 31, 29}, // 4ea1 + {0.485840f, 0.633789f, 0.500977f, 0.647949f, -0.0625f, -28.6875f, 30.0000f, 31, 29}, // 4ea1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea3 - {0.336914f, 0.352051f, 0.352051f, 0.367188f, 0.0625f, -28.6875f, 30.0000f, 31, 31}, // 4ea4 + {0.687500f, 0.376465f, 0.702637f, 0.391602f, 0.0625f, -28.6875f, 30.0000f, 31, 31}, // 4ea4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea6 - {0.125000f, 0.413574f, 0.139648f, 0.429199f, -1.3125f, -29.3125f, 30.0000f, 30, 32}, // 4ea7 + {0.861328f, 0.434082f, 0.875977f, 0.449707f, -1.3125f, -29.3125f, 30.0000f, 30, 32}, // 4ea7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ea9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eaa - {0.826172f, 0.488281f, 0.840820f, 0.503418f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 4eab - {0.352539f, 0.352051f, 0.367676f, 0.367188f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 4eac - {0.927246f, 0.367188f, 0.941406f, 0.382324f, 0.7500f, -29.1250f, 30.0000f, 29, 31}, // 4ead + {0.969238f, 0.509766f, 0.983887f, 0.524902f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 4eab + {0.770020f, 0.376465f, 0.785156f, 0.391602f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 4eac + {0.985352f, 0.606445f, 0.999512f, 0.621582f, 0.7500f, -29.1250f, 30.0000f, 29, 31}, // 4ead {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eaf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eb0 @@ -1308,38 +1609,38 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eb9 - {0.061035f, 0.488770f, 0.076172f, 0.503418f, 0.0625f, -28.1875f, 30.0000f, 31, 30}, // 4eba + {0.277344f, 0.510742f, 0.292480f, 0.525391f, 0.0625f, -28.1875f, 30.0000f, 31, 30}, // 4eba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ebb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ebc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ebd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ebe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ebf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec0 - {0.826660f, 0.032227f, 0.842285f, 0.047852f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 4ec1 + {0.505371f, 0.051758f, 0.520996f, 0.067383f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 4ec1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec4 - {0.937988f, 0.177246f, 0.953613f, 0.192383f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 4ec5 + {0.403320f, 0.199707f, 0.418945f, 0.214844f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 4ec5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ec9 - {0.631836f, 0.000000f, 0.647949f, 0.015625f, -1.0625f, -29.1250f, 30.0000f, 33, 32}, // 4eca - {0.954102f, 0.177246f, 0.969238f, 0.192871f, -0.4375f, -29.7500f, 30.0000f, 31, 32}, // 4ecb + {0.443848f, 0.022461f, 0.459961f, 0.038086f, -1.0625f, -29.1250f, 30.0000f, 33, 32}, // 4eca + {0.650879f, 0.199707f, 0.666016f, 0.215332f, -0.4375f, -29.7500f, 30.0000f, 31, 32}, // 4ecb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ecc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ecd - {0.648438f, 0.000000f, 0.664551f, 0.015625f, -1.5000f, -29.1250f, 30.0000f, 33, 32}, // 4ece - {0.624023f, 0.352051f, 0.639160f, 0.367188f, -0.7500f, -29.1250f, 30.0000f, 31, 31}, // 4ecf + {0.460449f, 0.022461f, 0.476563f, 0.038086f, -1.5000f, -29.1250f, 30.0000f, 33, 32}, // 4ece + {0.206543f, 0.376953f, 0.221680f, 0.392090f, -0.7500f, -29.1250f, 30.0000f, 31, 31}, // 4ecf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed4 - {0.655762f, 0.352051f, 0.670898f, 0.367188f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 4ed5 - {0.842773f, 0.032227f, 0.858398f, 0.047852f, -1.0625f, -29.3750f, 30.0000f, 32, 32}, // 4ed6 + {0.491211f, 0.376953f, 0.506348f, 0.392090f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 4ed5 + {0.521484f, 0.051758f, 0.537109f, 0.067383f, -1.0625f, -29.3750f, 30.0000f, 32, 32}, // 4ed6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ed7 - {0.969727f, 0.177246f, 0.984863f, 0.192871f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 4ed8 - {0.030762f, 0.489258f, 0.045410f, 0.504395f, -0.7500f, -28.6875f, 30.0000f, 30, 31}, // 4ed9 + {0.354980f, 0.201172f, 0.370117f, 0.216797f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 4ed8 + {0.453125f, 0.510742f, 0.467773f, 0.525879f, -0.7500f, -28.6875f, 30.0000f, 30, 31}, // 4ed9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4edb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4edc @@ -1349,9 +1650,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee2 - {0.511719f, 0.177734f, 0.527344f, 0.192871f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 4ee3 - {0.858887f, 0.032227f, 0.874512f, 0.047852f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 4ee4 - {0.154297f, 0.489258f, 0.169434f, 0.503906f, 0.0000f, -28.0625f, 30.0000f, 31, 30}, // 4ee5 + {0.693359f, 0.201172f, 0.708984f, 0.216309f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 4ee3 + {0.968262f, 0.051758f, 0.983887f, 0.067383f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 4ee4 + {0.951660f, 0.510742f, 0.966797f, 0.525391f, 0.0000f, -28.0625f, 30.0000f, 31, 30}, // 4ee5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ee8 @@ -1360,26 +1661,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eeb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eed - {0.897461f, 0.032227f, 0.913086f, 0.047852f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4eee + {0.909180f, 0.052246f, 0.924805f, 0.067871f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4eee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eef - {0.644043f, 0.177734f, 0.659180f, 0.193359f, -1.1250f, -29.6250f, 30.0000f, 31, 32}, // 4ef0 + {0.809570f, 0.201172f, 0.824707f, 0.216797f, -1.1250f, -29.6250f, 30.0000f, 31, 32}, // 4ef0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef1 - {0.493164f, 0.413574f, 0.507813f, 0.429199f, -0.5625f, -29.0000f, 30.0000f, 30, 32}, // 4ef2 + {0.829102f, 0.434570f, 0.843750f, 0.450195f, -0.5625f, -29.0000f, 30.0000f, 30, 32}, // 4ef2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef5 - {0.913574f, 0.032227f, 0.929199f, 0.047852f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 4ef6 + {0.944824f, 0.052734f, 0.960449f, 0.068359f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 4ef6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ef9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4efa - {0.929688f, 0.032227f, 0.945313f, 0.047852f, -1.2500f, -28.9375f, 30.0000f, 32, 32}, // 4efb + {0.790527f, 0.054199f, 0.806152f, 0.069824f, -1.2500f, -28.9375f, 30.0000f, 32, 32}, // 4efb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4efc - {0.945801f, 0.032227f, 0.961426f, 0.047852f, -0.5625f, -28.8750f, 30.0000f, 32, 32}, // 4efd + {0.433594f, 0.054688f, 0.449219f, 0.070313f, -0.5625f, -28.8750f, 30.0000f, 32, 32}, // 4efd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4efe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4eff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f00 - {0.817871f, 0.177734f, 0.833496f, 0.192871f, -1.1875f, -29.2500f, 30.0000f, 32, 31}, // 4f01 + {0.825195f, 0.201660f, 0.840820f, 0.216797f, -1.1875f, -29.2500f, 30.0000f, 32, 31}, // 4f01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f04 @@ -1393,9 +1694,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f0e - {0.961914f, 0.032227f, 0.977539f, 0.047852f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 4f0f - {0.527832f, 0.178223f, 0.543457f, 0.193359f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 4f10 - {0.978027f, 0.032227f, 0.993652f, 0.047852f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 4f11 + {0.449707f, 0.054688f, 0.465332f, 0.070313f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 4f0f + {0.209961f, 0.203125f, 0.225586f, 0.218262f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 4f10 + {0.698242f, 0.054688f, 0.713867f, 0.070313f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 4f11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f14 @@ -1404,10 +1705,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f19 - {0.273926f, 0.178711f, 0.289551f, 0.193848f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 4f1a + {0.226074f, 0.203125f, 0.241699f, 0.218262f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 4f1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f1c - {0.705078f, 0.352051f, 0.720215f, 0.367188f, -0.6875f, -29.0625f, 30.0000f, 31, 31}, // 4f1d + {0.539551f, 0.376953f, 0.554688f, 0.392090f, -0.6875f, -29.0625f, 30.0000f, 31, 31}, // 4f1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f20 @@ -1425,20 +1726,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f2e - {0.786621f, 0.552734f, 0.800781f, 0.568359f, -0.1250f, -29.3125f, 30.0000f, 29, 32}, // 4f2f + {0.091797f, 0.577637f, 0.105957f, 0.593262f, -0.1250f, -29.3125f, 30.0000f, 29, 32}, // 4f2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f33 - {0.290039f, 0.178711f, 0.305664f, 0.193848f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 4f34 + {0.242188f, 0.203125f, 0.257813f, 0.218262f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 4f34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f37 - {0.508301f, 0.413574f, 0.522949f, 0.429199f, -0.6250f, -29.3125f, 30.0000f, 30, 32}, // 4f38 + {0.093750f, 0.435059f, 0.108398f, 0.450684f, -0.6250f, -29.3125f, 30.0000f, 30, 32}, // 4f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f39 - {0.602539f, 0.413574f, 0.617188f, 0.429199f, -0.5000f, -29.0000f, 30.0000f, 30, 32}, // 4f3a + {0.894531f, 0.435059f, 0.909180f, 0.450684f, -0.5000f, -29.0000f, 30.0000f, 30, 32}, // 4f3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f3b - {0.570313f, 0.032715f, 0.585938f, 0.048340f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 4f3c + {0.391602f, 0.056152f, 0.407227f, 0.071777f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 4f3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f3f @@ -1448,33 +1749,33 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f45 - {0.875000f, 0.032715f, 0.890625f, 0.048340f, -1.1250f, -29.1875f, 30.0000f, 32, 32}, // 4f46 + {0.738770f, 0.056152f, 0.754395f, 0.071777f, -1.1250f, -29.1875f, 30.0000f, 32, 32}, // 4f46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f47 - {0.586426f, 0.033203f, 0.602051f, 0.048828f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 4f48 + {0.869141f, 0.056152f, 0.884766f, 0.071777f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 4f48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f4c - {0.306152f, 0.178711f, 0.321777f, 0.193848f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 4f4d - {0.309570f, 0.033691f, 0.325195f, 0.049316f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 4f4e - {0.325684f, 0.033691f, 0.341309f, 0.049316f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 4f4f - {0.341797f, 0.033691f, 0.357422f, 0.049316f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 4f50 + {0.516602f, 0.203125f, 0.532227f, 0.218262f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 4f4d + {0.885254f, 0.056641f, 0.900879f, 0.072266f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 4f4e + {0.242676f, 0.058105f, 0.258301f, 0.073730f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 4f4f + {0.258789f, 0.058105f, 0.274414f, 0.073730f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 4f50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f52 - {0.451172f, 0.178711f, 0.466797f, 0.193848f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 4f53 + {0.532715f, 0.203125f, 0.548340f, 0.218262f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 4f53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f54 - {0.518066f, 0.033691f, 0.533691f, 0.049316f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4f55 + {0.274902f, 0.058105f, 0.290527f, 0.073730f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4f55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f58 - {0.467285f, 0.178711f, 0.482422f, 0.194336f, -0.1875f, -29.5625f, 30.0000f, 31, 32}, // 4f59 + {0.666504f, 0.203613f, 0.681641f, 0.219238f, -0.1875f, -29.5625f, 30.0000f, 31, 32}, // 4f59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f5b - {0.534180f, 0.033691f, 0.549805f, 0.049316f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 4f5c + {0.576660f, 0.058105f, 0.592285f, 0.073730f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 4f5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f5f - {0.665039f, 0.000000f, 0.681152f, 0.015625f, -1.5625f, -29.0000f, 30.0000f, 33, 32}, // 4f60 + {0.752930f, 0.023926f, 0.769043f, 0.039551f, -1.5625f, -29.0000f, 30.0000f, 33, 32}, // 4f60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f63 @@ -1493,9 +1794,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f72 - {0.488770f, 0.034180f, 0.504395f, 0.049805f, -1.4375f, -29.0000f, 30.0000f, 32, 32}, // 4f73 + {0.592773f, 0.058105f, 0.608398f, 0.073730f, -1.4375f, -29.0000f, 30.0000f, 32, 32}, // 4f73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f74 - {0.550293f, 0.035156f, 0.565918f, 0.050781f, -0.9375f, -29.5625f, 30.0000f, 32, 32}, // 4f75 + {0.714355f, 0.058594f, 0.729980f, 0.074219f, -0.9375f, -29.5625f, 30.0000f, 32, 32}, // 4f75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f78 @@ -1505,7 +1806,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f7e - {0.681641f, 0.000000f, 0.697754f, 0.015625f, -0.5000f, -29.1250f, 30.0000f, 33, 32}, // 4f7f + {0.877441f, 0.023926f, 0.893555f, 0.039551f, -0.5000f, -29.1250f, 30.0000f, 33, 32}, // 4f7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f82 @@ -1517,9 +1818,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f8a - {0.435059f, 0.179199f, 0.450195f, 0.194824f, -0.8125f, -29.3750f, 30.0000f, 31, 32}, // 4f8b + {0.709473f, 0.203613f, 0.724609f, 0.219238f, -0.8125f, -29.3750f, 30.0000f, 31, 32}, // 4f8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f8c - {0.685547f, 0.179199f, 0.700684f, 0.194824f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 4f8d + {0.725098f, 0.203613f, 0.740234f, 0.219238f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 4f8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f90 @@ -1533,13 +1834,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f9a - {0.234375f, 0.035645f, 0.250000f, 0.051270f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 4f9b + {0.754883f, 0.058594f, 0.770508f, 0.074219f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 4f9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f9c - {0.250488f, 0.035645f, 0.266113f, 0.051270f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 4f9d + {0.770996f, 0.058594f, 0.786621f, 0.074219f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 4f9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4f9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fa0 - {0.482910f, 0.180176f, 0.498535f, 0.195313f, -1.3125f, -29.0625f, 30.0000f, 32, 31}, // 4fa1 + {0.579590f, 0.204102f, 0.595215f, 0.219238f, -1.3125f, -29.0625f, 30.0000f, 32, 31}, // 4fa1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fa2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fa3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fa4 @@ -1552,14 +1853,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fad - {0.266602f, 0.035645f, 0.282227f, 0.051270f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4fae - {0.282715f, 0.035645f, 0.298340f, 0.051270f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 4faf + {0.631348f, 0.059082f, 0.646973f, 0.074707f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4fae + {0.647461f, 0.059082f, 0.663086f, 0.074707f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 4faf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb4 - {0.392578f, 0.037109f, 0.408203f, 0.052734f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4fb5 + {0.063477f, 0.059570f, 0.079102f, 0.075195f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 4fb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fb8 @@ -1569,18 +1870,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fbe - {0.442871f, 0.040039f, 0.458496f, 0.055664f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 4fbf + {0.079590f, 0.059570f, 0.095215f, 0.075195f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 4fbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc1 - {0.458984f, 0.040527f, 0.474609f, 0.056152f, -0.8750f, -29.3750f, 30.0000f, 32, 32}, // 4fc2 - {0.698242f, 0.000000f, 0.714355f, 0.015625f, -1.4375f, -29.1875f, 30.0000f, 33, 32}, // 4fc3 + {0.095703f, 0.059570f, 0.111328f, 0.075195f, -0.8750f, -29.3750f, 30.0000f, 32, 32}, // 4fc2 + {0.894043f, 0.024414f, 0.910156f, 0.040039f, -1.4375f, -29.1875f, 30.0000f, 33, 32}, // 4fc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fc9 - {0.141602f, 0.041992f, 0.157227f, 0.057617f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 4fca + {0.663574f, 0.060059f, 0.679199f, 0.075684f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 4fca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fcb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fcc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fcd @@ -1593,17 +1894,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fd6 - {0.714844f, 0.000000f, 0.730957f, 0.015625f, -0.9375f, -29.1875f, 30.0000f, 33, 32}, // 4fd7 + {0.582031f, 0.025879f, 0.598145f, 0.041504f, -0.9375f, -29.1875f, 30.0000f, 33, 32}, // 4fd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fdb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fdc - {0.157715f, 0.041992f, 0.173340f, 0.057617f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 4fdd + {0.679688f, 0.060059f, 0.695313f, 0.075684f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 4fdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fdf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fe0 - {0.209961f, 0.180664f, 0.225586f, 0.195801f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 4fe1 + {0.595703f, 0.204102f, 0.611328f, 0.219238f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 4fe1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fe2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fe3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fe4 @@ -1616,17 +1917,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4feb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fed - {0.731445f, 0.000000f, 0.747559f, 0.015625f, -1.0625f, -29.3750f, 30.0000f, 33, 32}, // 4fee + {0.598633f, 0.025879f, 0.614746f, 0.041504f, -1.0625f, -29.3750f, 30.0000f, 33, 32}, // 4fee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4fef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff2 - {0.357910f, 0.042480f, 0.373535f, 0.058105f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 4ff3 + {0.167480f, 0.061035f, 0.183105f, 0.076660f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 4ff3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff4 - {0.374023f, 0.042480f, 0.389648f, 0.058105f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 4ff5 + {0.209961f, 0.061035f, 0.225586f, 0.076660f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 4ff5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff7 - {0.060547f, 0.044922f, 0.076172f, 0.060547f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // 4ff8 + {0.226074f, 0.061035f, 0.241699f, 0.076660f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // 4ff8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ff9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ffa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 4ffb @@ -1643,41 +1944,41 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5006 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5007 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5008 - {0.226074f, 0.180664f, 0.241211f, 0.196289f, -0.1875f, -29.6875f, 30.0000f, 31, 32}, // 5009 + {0.047852f, 0.204590f, 0.062988f, 0.220215f, -0.1875f, -29.6875f, 30.0000f, 31, 32}, // 5009 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 500a - {0.241699f, 0.180664f, 0.256836f, 0.196289f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 500b + {0.063477f, 0.204590f, 0.078613f, 0.220215f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 500b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 500c - {0.076660f, 0.044922f, 0.092285f, 0.060547f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 500d + {0.183594f, 0.061523f, 0.199219f, 0.077148f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 500d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 500e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 500f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5010 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5011 - {0.926270f, 0.413574f, 0.940918f, 0.429199f, -0.4375f, -29.1875f, 30.0000f, 30, 32}, // 5012 + {0.347656f, 0.435547f, 0.362305f, 0.451172f, -0.4375f, -29.1875f, 30.0000f, 30, 32}, // 5012 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5013 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5014 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5015 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5016 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5017 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5018 - {0.748047f, 0.000000f, 0.764160f, 0.015625f, -1.4375f, -29.3125f, 30.0000f, 33, 32}, // 5019 + {0.724121f, 0.026367f, 0.740234f, 0.041992f, -1.4375f, -29.3125f, 30.0000f, 33, 32}, // 5019 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 501a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 501b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 501c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 501d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 501e - {0.092773f, 0.044922f, 0.108398f, 0.060547f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 501f + {0.000000f, 0.062500f, 0.015625f, 0.078125f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 501f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5020 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5021 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5022 - {0.764648f, 0.000000f, 0.780762f, 0.015625f, -1.1875f, -29.4375f, 30.0000f, 33, 32}, // 5023 - {0.108887f, 0.044922f, 0.124512f, 0.060547f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 5024 + {0.769531f, 0.026367f, 0.785645f, 0.041992f, -1.1875f, -29.4375f, 30.0000f, 33, 32}, // 5023 + {0.016113f, 0.062500f, 0.031738f, 0.078125f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 5024 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5025 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5026 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5027 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5028 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5029 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 502a - {0.781250f, 0.000000f, 0.797363f, 0.015625f, -1.1250f, -29.6875f, 30.0000f, 33, 32}, // 502b + {0.786133f, 0.026367f, 0.802246f, 0.041992f, -1.1250f, -29.6875f, 30.0000f, 33, 32}, // 502b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 502c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 502d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 502e @@ -1691,10 +1992,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5036 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5037 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5038 - {0.125000f, 0.046875f, 0.140625f, 0.062500f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5039 + {0.032227f, 0.062500f, 0.047852f, 0.078125f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5039 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 503a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 503b - {0.173828f, 0.047363f, 0.189453f, 0.062988f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 503c + {0.806641f, 0.062988f, 0.822266f, 0.078613f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 503c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 503d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 503e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 503f @@ -1707,13 +2008,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5046 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5047 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5048 - {0.217773f, 0.047363f, 0.233398f, 0.062988f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 5049 + {0.822754f, 0.062988f, 0.838379f, 0.078613f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 5049 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 504a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 504b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 504c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 504d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 504e - {0.257324f, 0.180664f, 0.272461f, 0.196289f, -0.8750f, -29.1250f, 30.0000f, 31, 32}, // 504f + {0.079102f, 0.204590f, 0.094238f, 0.220215f, -0.8750f, -29.1250f, 30.0000f, 31, 32}, // 504f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5050 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5051 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5052 @@ -1726,7 +2027,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5059 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 505a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 505b - {0.353516f, 0.182129f, 0.368652f, 0.197754f, -0.9375f, -29.0625f, 30.0000f, 31, 32}, // 505c + {0.611816f, 0.205078f, 0.626953f, 0.220703f, -0.9375f, -29.0625f, 30.0000f, 31, 32}, // 505c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 505d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 505e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 505f @@ -1735,7 +2036,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5062 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5063 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5064 - {0.408691f, 0.047363f, 0.424316f, 0.062988f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5065 + {0.308594f, 0.063477f, 0.324219f, 0.079102f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5065 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5066 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5067 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5068 @@ -1750,16 +2051,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5071 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5073 - {0.957031f, 0.413574f, 0.971680f, 0.429199f, -0.8125f, -29.0625f, 30.0000f, 30, 32}, // 5074 - {0.401855f, 0.185059f, 0.416992f, 0.200684f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5075 - {0.785645f, 0.352051f, 0.800781f, 0.367188f, -0.8750f, -29.1250f, 30.0000f, 31, 31}, // 5076 + {0.604980f, 0.436035f, 0.619629f, 0.451660f, -0.8125f, -29.0625f, 30.0000f, 30, 32}, // 5074 + {0.627441f, 0.205078f, 0.642578f, 0.220703f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5075 + {0.555176f, 0.376953f, 0.570313f, 0.392090f, -0.8750f, -29.1250f, 30.0000f, 31, 31}, // 5076 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5077 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5078 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5079 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 507a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 507b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 507c - {0.417480f, 0.185547f, 0.432617f, 0.201172f, -0.8125f, -29.0625f, 30.0000f, 31, 32}, // 507d + {0.193359f, 0.205566f, 0.208496f, 0.221191f, -0.8125f, -29.0625f, 30.0000f, 31, 32}, // 507d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 507e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 507f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5080 @@ -1775,19 +2076,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 508a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 508b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 508c - {0.116211f, 0.186523f, 0.131836f, 0.201660f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 508d + {0.130859f, 0.206055f, 0.146484f, 0.221191f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 508d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 508e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 508f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5090 - {0.797852f, 0.000000f, 0.813965f, 0.015625f, -1.1250f, -29.4375f, 30.0000f, 33, 32}, // 5091 + {0.639160f, 0.026855f, 0.655273f, 0.042480f, -1.1250f, -29.4375f, 30.0000f, 33, 32}, // 5091 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5092 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5093 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5094 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5095 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5096 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5097 - {0.424805f, 0.047363f, 0.440430f, 0.062988f, -0.5000f, -29.4375f, 30.0000f, 32, 32}, // 5098 - {0.715820f, 0.047363f, 0.731445f, 0.062988f, -1.1875f, -29.0625f, 30.0000f, 32, 32}, // 5099 + {0.324707f, 0.063477f, 0.340332f, 0.079102f, -0.5000f, -29.4375f, 30.0000f, 32, 32}, // 5098 + {0.340820f, 0.063477f, 0.356445f, 0.079102f, -1.1875f, -29.0625f, 30.0000f, 32, 32}, // 5099 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 509a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 509b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 509c @@ -1802,11 +2103,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50a7 - {0.816406f, 0.352051f, 0.831543f, 0.367188f, -1.1875f, -29.0000f, 30.0000f, 31, 31}, // 50a8 + {0.669434f, 0.376953f, 0.684570f, 0.392090f, -1.1875f, -29.0000f, 30.0000f, 31, 31}, // 50a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ab - {0.189941f, 0.047852f, 0.205566f, 0.063477f, -1.1250f, -29.2500f, 30.0000f, 32, 32}, // 50ac + {0.356934f, 0.063477f, 0.372559f, 0.079102f, -1.1250f, -29.2500f, 30.0000f, 32, 32}, // 50ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50af @@ -1815,16 +2116,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b4 - {0.602539f, 0.048340f, 0.618164f, 0.063965f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 50b5 + {0.373047f, 0.063477f, 0.388672f, 0.079102f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 50b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b6 - {0.618652f, 0.048340f, 0.634277f, 0.063965f, -1.1250f, -29.1875f, 30.0000f, 32, 32}, // 50b7 + {0.291016f, 0.063965f, 0.306641f, 0.079590f, -1.1250f, -29.1875f, 30.0000f, 32, 32}, // 50b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50bd - {0.322266f, 0.187012f, 0.337891f, 0.202148f, -1.0000f, -29.0000f, 30.0000f, 32, 31}, // 50be + {0.146973f, 0.206055f, 0.162598f, 0.221191f, -1.0000f, -29.0000f, 30.0000f, 32, 31}, // 50be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50c1 @@ -1839,20 +2140,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50cc - {0.880371f, 0.352051f, 0.895508f, 0.367188f, -0.7500f, -29.0000f, 30.0000f, 31, 31}, // 50cd + {0.048340f, 0.377441f, 0.063477f, 0.392578f, -0.7500f, -29.0000f, 30.0000f, 31, 31}, // 50cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ce - {0.634766f, 0.048340f, 0.650391f, 0.063965f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 50cf + {0.537598f, 0.064941f, 0.553223f, 0.080566f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 50cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d4 - {0.000000f, 0.187988f, 0.015625f, 0.203125f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 50d5 + {0.163086f, 0.206055f, 0.178711f, 0.221191f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 50d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50d9 - {0.814453f, 0.000000f, 0.830566f, 0.015625f, -0.8125f, -29.2500f, 30.0000f, 33, 32}, // 50da + {0.655762f, 0.026855f, 0.671875f, 0.042480f, -0.8125f, -29.2500f, 30.0000f, 33, 32}, // 50da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50dd @@ -1865,7 +2166,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50e6 - {0.016113f, 0.187988f, 0.031250f, 0.203613f, -0.8750f, -29.3125f, 30.0000f, 31, 32}, // 50e7 + {0.000000f, 0.207031f, 0.015137f, 0.222656f, -0.8750f, -29.3125f, 30.0000f, 31, 32}, // 50e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ea @@ -1890,11 +2191,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 50ff - {0.650879f, 0.048340f, 0.666504f, 0.063965f, -0.8750f, -29.3750f, 30.0000f, 32, 32}, // 5100 + {0.553711f, 0.064941f, 0.569336f, 0.080566f, -0.8750f, -29.3750f, 30.0000f, 32, 32}, // 5100 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5101 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5102 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5103 - {0.666992f, 0.048340f, 0.682617f, 0.063965f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5104 + {0.838867f, 0.064941f, 0.854492f, 0.080566f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5104 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5105 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5106 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5107 @@ -1908,7 +2209,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 510f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5110 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5111 - {0.031738f, 0.189453f, 0.047363f, 0.204590f, -1.0000f, -29.1875f, 30.0000f, 32, 31}, // 5112 + {0.015625f, 0.207031f, 0.031250f, 0.222168f, -1.0000f, -29.1875f, 30.0000f, 32, 31}, // 5112 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5113 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5114 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5115 @@ -1921,7 +2222,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 511c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 511d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 511e - {0.831055f, 0.000000f, 0.847168f, 0.015625f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 511f + {0.672363f, 0.027832f, 0.688477f, 0.043457f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 511f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5120 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5121 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5122 @@ -1932,7 +2233,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5127 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5128 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5129 - {0.683105f, 0.048340f, 0.698730f, 0.063965f, -1.1250f, -29.0625f, 30.0000f, 32, 32}, // 512a + {0.925293f, 0.066406f, 0.940918f, 0.082031f, -1.1250f, -29.0625f, 30.0000f, 32, 32}, // 512a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 512b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 512c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 512d @@ -1940,7 +2241,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 512f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5130 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5131 - {0.762207f, 0.048340f, 0.777832f, 0.063965f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5132 + {0.407715f, 0.067871f, 0.423340f, 0.083496f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5132 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5133 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5134 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5135 @@ -1957,20 +2258,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5140 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5141 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5142 - {0.029785f, 0.643555f, 0.044434f, 0.657715f, 0.2500f, -27.0000f, 30.0000f, 30, 29}, // 5143 - {0.527344f, 0.583008f, 0.541992f, 0.597656f, 0.5000f, -27.2500f, 30.0000f, 30, 30}, // 5144 - {0.895996f, 0.352051f, 0.911133f, 0.367188f, -0.1250f, -28.6875f, 30.0000f, 31, 31}, // 5145 - {0.533203f, 0.489258f, 0.547852f, 0.504395f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 5146 + {0.193848f, 0.671875f, 0.208496f, 0.686035f, 0.2500f, -27.0000f, 30.0000f, 30, 29}, // 5143 + {0.766602f, 0.608887f, 0.781250f, 0.623535f, 0.5000f, -27.2500f, 30.0000f, 30, 30}, // 5144 + {0.175781f, 0.377441f, 0.190918f, 0.392578f, -0.1250f, -28.6875f, 30.0000f, 31, 31}, // 5145 + {0.902344f, 0.511230f, 0.916992f, 0.526367f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 5146 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5147 - {0.972168f, 0.413574f, 0.986816f, 0.429199f, 0.6250f, -29.1875f, 30.0000f, 30, 32}, // 5148 - {0.679688f, 0.489746f, 0.694336f, 0.504883f, -0.0625f, -29.0000f, 30.0000f, 30, 31}, // 5149 + {0.362793f, 0.436523f, 0.377441f, 0.452148f, 0.6250f, -29.1875f, 30.0000f, 30, 32}, // 5148 + {0.848633f, 0.511719f, 0.863281f, 0.526855f, -0.0625f, -29.0000f, 30.0000f, 30, 31}, // 5149 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 514a - {0.338379f, 0.188965f, 0.353516f, 0.204590f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 514b + {0.758301f, 0.207520f, 0.773438f, 0.223145f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 514b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 514c - {0.047852f, 0.189453f, 0.062988f, 0.205078f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 514d + {0.773926f, 0.207520f, 0.789063f, 0.223145f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 514d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 514e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 514f - {0.241699f, 0.603516f, 0.256836f, 0.617676f, -0.5000f, -26.1250f, 30.0000f, 31, 29}, // 5150 + {0.890137f, 0.633789f, 0.905273f, 0.647949f, -0.5000f, -26.1250f, 30.0000f, 31, 29}, // 5150 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5151 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5152 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5153 @@ -1980,7 +2281,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5157 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5158 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5159 - {0.190918f, 0.352539f, 0.206055f, 0.367676f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 515a + {0.191406f, 0.377441f, 0.206543f, 0.392578f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 515a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 515b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 515c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 515d @@ -1991,30 +2292,30 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5162 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5163 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5164 - {0.518066f, 0.644043f, 0.532715f, 0.658203f, 0.5000f, -27.1250f, 30.0000f, 30, 29}, // 5165 + {0.059082f, 0.672363f, 0.073730f, 0.686523f, 0.5000f, -27.1250f, 30.0000f, 30, 29}, // 5165 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5166 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5167 - {0.350098f, 0.603516f, 0.365234f, 0.617676f, -0.8125f, -28.1250f, 30.0000f, 31, 29}, // 5168 - {0.709961f, 0.489746f, 0.725098f, 0.504395f, -0.1875f, -27.5000f, 30.0000f, 31, 30}, // 5169 + {0.867188f, 0.634766f, 0.882324f, 0.648926f, -0.8125f, -28.1250f, 30.0000f, 31, 29}, // 5168 + {0.391113f, 0.512207f, 0.406250f, 0.526855f, -0.1875f, -27.5000f, 30.0000f, 31, 30}, // 5169 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 516a - {0.899414f, 0.553223f, 0.915039f, 0.567383f, -0.6875f, -27.7500f, 30.0000f, 32, 29}, // 516b - {0.140137f, 0.414063f, 0.155762f, 0.428711f, -0.5000f, -28.1875f, 30.0000f, 32, 30}, // 516c - {0.548340f, 0.490723f, 0.563477f, 0.505371f, -0.1875f, -28.3125f, 30.0000f, 31, 30}, // 516d + {0.291504f, 0.578125f, 0.307129f, 0.592285f, -0.6875f, -27.7500f, 30.0000f, 32, 29}, // 516b + {0.695801f, 0.436523f, 0.711426f, 0.451172f, -0.5000f, -28.1875f, 30.0000f, 32, 30}, // 516c + {0.817871f, 0.512207f, 0.833008f, 0.526855f, -0.1875f, -28.3125f, 30.0000f, 31, 30}, // 516d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 516e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 516f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5170 - {0.411621f, 0.414063f, 0.426270f, 0.429688f, 0.1875f, -28.9375f, 30.0000f, 30, 32}, // 5171 + {0.315918f, 0.437500f, 0.330566f, 0.453125f, 0.1875f, -28.9375f, 30.0000f, 30, 32}, // 5171 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5172 - {0.444824f, 0.352539f, 0.459961f, 0.367676f, -0.9375f, -29.0000f, 30.0000f, 31, 31}, // 5173 + {0.570801f, 0.377441f, 0.585938f, 0.392578f, -0.9375f, -29.0000f, 30.0000f, 31, 31}, // 5173 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5174 - {0.063477f, 0.189453f, 0.079102f, 0.204590f, -0.4375f, -28.5625f, 30.0000f, 32, 31}, // 5175 - {0.493164f, 0.352539f, 0.508301f, 0.367676f, -0.1250f, -29.0000f, 30.0000f, 31, 31}, // 5176 - {0.563965f, 0.490723f, 0.579102f, 0.505371f, -0.1250f, -27.6875f, 30.0000f, 31, 30}, // 5177 - {0.079590f, 0.189453f, 0.094727f, 0.205078f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 5178 + {0.274414f, 0.208008f, 0.290039f, 0.223145f, -0.4375f, -28.5625f, 30.0000f, 32, 31}, // 5175 + {0.144043f, 0.377930f, 0.159180f, 0.393066f, -0.1250f, -29.0000f, 30.0000f, 31, 31}, // 5176 + {0.327148f, 0.512695f, 0.342285f, 0.527344f, -0.1250f, -27.6875f, 30.0000f, 31, 30}, // 5177 + {0.290527f, 0.208008f, 0.305664f, 0.223633f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 5178 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5179 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 517a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 517b - {0.778320f, 0.048340f, 0.793945f, 0.063965f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 517c + {0.465820f, 0.067871f, 0.481445f, 0.083496f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 517c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 517d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 517e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 517f @@ -2023,34 +2324,34 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5182 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5183 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5184 - {0.572754f, 0.429199f, 0.585938f, 0.444336f, 1.9375f, -28.7500f, 30.0000f, 27, 31}, // 5185 - {0.738770f, 0.746582f, 0.750977f, 0.760742f, 2.5000f, -27.4375f, 30.0000f, 25, 29}, // 5186 + {0.490234f, 0.704102f, 0.503418f, 0.719238f, 1.9375f, -28.7500f, 30.0000f, 27, 31}, // 5185 + {0.012695f, 0.805176f, 0.024902f, 0.819336f, 2.5000f, -27.4375f, 30.0000f, 25, 29}, // 5186 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5187 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5188 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5189 - {0.757813f, 0.490723f, 0.772949f, 0.505371f, -0.5000f, -27.6875f, 30.0000f, 31, 30}, // 518a + {0.375977f, 0.512695f, 0.391113f, 0.527344f, -0.5000f, -27.6875f, 30.0000f, 31, 30}, // 518a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 518b - {0.569824f, 0.414063f, 0.585449f, 0.428711f, -0.6250f, -27.6250f, 30.0000f, 32, 30}, // 518c - {0.486816f, 0.491211f, 0.501953f, 0.505859f, 0.0000f, -27.7500f, 30.0000f, 31, 30}, // 518d + {0.647461f, 0.437500f, 0.663086f, 0.452148f, -0.6250f, -27.6250f, 30.0000f, 32, 30}, // 518c + {0.984375f, 0.512695f, 0.999512f, 0.527344f, 0.0000f, -27.7500f, 30.0000f, 31, 30}, // 518d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 518e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 518f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5190 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5191 - {0.908203f, 0.666016f, 0.921387f, 0.681152f, 1.9375f, -28.3125f, 30.0000f, 27, 31}, // 5192 + {0.579590f, 0.704102f, 0.592773f, 0.719238f, 1.9375f, -28.3125f, 30.0000f, 27, 31}, // 5192 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5193 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5194 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5195 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5196 - {0.853516f, 0.603516f, 0.868652f, 0.617676f, -0.3750f, -26.8750f, 30.0000f, 31, 29}, // 5197 + {0.303223f, 0.636230f, 0.318359f, 0.650391f, -0.3750f, -26.8750f, 30.0000f, 31, 29}, // 5197 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5198 - {0.579590f, 0.491211f, 0.594727f, 0.505859f, -0.0625f, -27.6250f, 30.0000f, 31, 30}, // 5199 + {0.678223f, 0.513184f, 0.693359f, 0.527832f, -0.0625f, -27.6250f, 30.0000f, 31, 30}, // 5199 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 519f - {0.749023f, 0.414063f, 0.764648f, 0.428711f, -0.5000f, -27.6250f, 30.0000f, 32, 30}, // 51a0 + {0.781250f, 0.438477f, 0.796875f, 0.453125f, -0.5000f, -27.6250f, 30.0000f, 32, 30}, // 51a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51a3 @@ -2062,18 +2363,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ab - {0.095215f, 0.191406f, 0.110352f, 0.207031f, 0.0000f, -29.6875f, 30.0000f, 31, 32}, // 51ac + {0.306152f, 0.208008f, 0.321289f, 0.223633f, 0.0000f, -29.6875f, 30.0000f, 31, 32}, // 51ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b1 - {0.169922f, 0.490234f, 0.184570f, 0.505371f, -0.7500f, -29.0000f, 30.0000f, 30, 31}, // 51b2 + {0.863770f, 0.513184f, 0.878418f, 0.528320f, -0.7500f, -29.0000f, 30.0000f, 30, 31}, // 51b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b6 - {0.794434f, 0.048340f, 0.810059f, 0.063965f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 51b7 + {0.481934f, 0.067871f, 0.497559f, 0.083496f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 51b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ba @@ -2088,14 +2389,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c5 - {0.132324f, 0.191895f, 0.147461f, 0.207520f, -0.3125f, -29.0625f, 30.0000f, 31, 32}, // 51c6 + {0.321777f, 0.208008f, 0.336914f, 0.223633f, -0.3125f, -29.0625f, 30.0000f, 31, 32}, // 51c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51cc - {0.178711f, 0.191895f, 0.194336f, 0.207031f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 51cd + {0.258301f, 0.208496f, 0.273926f, 0.223633f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 51cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51d0 @@ -2111,16 +2412,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51dc - {0.128906f, 0.170898f, 0.145020f, 0.186035f, -1.5625f, -28.5625f, 30.0000f, 33, 31}, // 51dd + {0.161133f, 0.190430f, 0.177246f, 0.205566f, -1.5625f, -28.5625f, 30.0000f, 33, 31}, // 51dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51df - {0.765137f, 0.414063f, 0.780762f, 0.428711f, -1.0000f, -27.2500f, 30.0000f, 32, 30}, // 51e0 - {0.747070f, 0.583008f, 0.761719f, 0.597656f, 0.1250f, -27.0625f, 30.0000f, 30, 30}, // 51e1 + {0.797363f, 0.438477f, 0.812988f, 0.453125f, -1.0000f, -27.2500f, 30.0000f, 32, 30}, // 51e0 + {0.089355f, 0.609863f, 0.104004f, 0.624512f, 0.1250f, -27.0625f, 30.0000f, 30, 30}, // 51e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e5 - {0.369141f, 0.191895f, 0.384766f, 0.207031f, -1.5000f, -28.5625f, 30.0000f, 32, 31}, // 51e6 + {0.031738f, 0.208984f, 0.047363f, 0.224121f, -1.5000f, -28.5625f, 30.0000f, 32, 31}, // 51e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51e9 @@ -2136,76 +2437,76 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51f5 - {0.203613f, 0.691406f, 0.216797f, 0.705566f, 1.8750f, -27.3125f, 30.0000f, 27, 29}, // 51f6 + {0.753418f, 0.730469f, 0.766602f, 0.744629f, 1.8750f, -27.3125f, 30.0000f, 27, 29}, // 51f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51f7 - {0.937012f, 0.677734f, 0.950195f, 0.692383f, 2.3125f, -27.3125f, 30.0000f, 27, 30}, // 51f8 - {0.279297f, 0.691406f, 0.292480f, 0.705566f, 1.7500f, -27.2500f, 30.0000f, 27, 29}, // 51f9 - {0.028320f, 0.674316f, 0.041016f, 0.689941f, 2.3125f, -29.1250f, 30.0000f, 26, 32}, // 51fa + {0.753418f, 0.715332f, 0.766602f, 0.729980f, 2.3125f, -27.3125f, 30.0000f, 27, 30}, // 51f8 + {0.263184f, 0.730957f, 0.276367f, 0.745117f, 1.7500f, -27.2500f, 30.0000f, 27, 29}, // 51f9 + {0.132324f, 0.706055f, 0.145020f, 0.721680f, 2.3125f, -29.1250f, 30.0000f, 26, 32}, // 51fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51fc - {0.666016f, 0.583496f, 0.680664f, 0.598145f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // 51fd + {0.104492f, 0.609863f, 0.119141f, 0.624512f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // 51fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 51ff - {0.528809f, 0.690430f, 0.542480f, 0.704102f, 0.5000f, -26.8125f, 30.0000f, 28, 28}, // 5200 + {0.294434f, 0.727539f, 0.308105f, 0.741211f, 0.5000f, -26.8125f, 30.0000f, 28, 28}, // 5200 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5201 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5202 - {0.591309f, 0.662109f, 0.605469f, 0.676270f, -0.6875f, -26.8750f, 30.0000f, 29, 29}, // 5203 + {0.253418f, 0.693359f, 0.267578f, 0.707520f, -0.6875f, -26.8750f, 30.0000f, 29, 29}, // 5203 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5204 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5205 - {0.649414f, 0.491211f, 0.664551f, 0.505859f, -0.0625f, -27.3750f, 30.0000f, 31, 30}, // 5206 - {0.810059f, 0.491211f, 0.824707f, 0.506348f, -0.6875f, -27.9375f, 30.0000f, 30, 31}, // 5207 - {0.958496f, 0.382813f, 0.972656f, 0.397949f, 0.3125f, -28.5000f, 30.0000f, 29, 31}, // 5208 + {0.595215f, 0.513672f, 0.610352f, 0.528320f, -0.0625f, -27.3750f, 30.0000f, 31, 30}, // 5206 + {0.878906f, 0.513672f, 0.893555f, 0.528809f, -0.6875f, -27.9375f, 30.0000f, 30, 31}, // 5207 + {0.411133f, 0.630859f, 0.425293f, 0.645996f, 0.3125f, -28.5000f, 30.0000f, 29, 31}, // 5208 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5209 - {0.274414f, 0.604004f, 0.288574f, 0.619141f, 0.0625f, -28.9375f, 30.0000f, 29, 31}, // 520a + {0.350586f, 0.636230f, 0.364746f, 0.651367f, 0.0625f, -28.9375f, 30.0000f, 29, 31}, // 520a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 520b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 520c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 520d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 520e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 520f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5210 - {0.908203f, 0.414063f, 0.922852f, 0.429688f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 5211 - {0.841309f, 0.491211f, 0.855957f, 0.506348f, -0.6875f, -29.0625f, 30.0000f, 30, 31}, // 5212 + {0.491699f, 0.438965f, 0.506348f, 0.454590f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 5211 + {0.342773f, 0.515137f, 0.357422f, 0.530273f, -0.6875f, -29.0625f, 30.0000f, 30, 31}, // 5212 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5213 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5214 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5215 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5216 - {0.833008f, 0.552734f, 0.847168f, 0.568359f, 0.4375f, -29.0000f, 30.0000f, 29, 32}, // 5217 + {0.337891f, 0.578125f, 0.352051f, 0.593750f, 0.4375f, -29.0000f, 30.0000f, 29, 32}, // 5217 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5218 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5219 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 521a - {0.903809f, 0.491211f, 0.918457f, 0.506348f, -0.7500f, -29.1250f, 30.0000f, 30, 31}, // 521b + {0.093750f, 0.515625f, 0.108398f, 0.530762f, -0.7500f, -29.1250f, 30.0000f, 30, 31}, // 521b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 521c - {0.254883f, 0.353027f, 0.270020f, 0.368164f, -1.0625f, -28.6875f, 30.0000f, 31, 31}, // 521d + {0.586426f, 0.377930f, 0.601563f, 0.393066f, -1.0625f, -28.6875f, 30.0000f, 31, 31}, // 521d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 521e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 521f - {0.311523f, 0.491699f, 0.326172f, 0.506836f, -1.2500f, -28.6250f, 30.0000f, 30, 31}, // 5220 + {0.292969f, 0.516113f, 0.307617f, 0.531250f, -1.2500f, -28.6250f, 30.0000f, 30, 31}, // 5220 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5221 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5222 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5223 - {0.941406f, 0.414063f, 0.956055f, 0.429688f, -0.2500f, -29.0000f, 30.0000f, 30, 32}, // 5224 - {0.423340f, 0.491699f, 0.437988f, 0.506836f, -0.4375f, -28.8125f, 30.0000f, 30, 31}, // 5225 + {0.620117f, 0.438965f, 0.634766f, 0.454590f, -0.2500f, -29.0000f, 30.0000f, 30, 32}, // 5224 + {0.308105f, 0.516113f, 0.322754f, 0.531250f, -0.4375f, -28.8125f, 30.0000f, 30, 31}, // 5225 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5226 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5227 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5228 - {0.611328f, 0.491699f, 0.625977f, 0.506836f, -0.3125f, -28.8125f, 30.0000f, 30, 31}, // 5229 - {0.665039f, 0.492188f, 0.679688f, 0.507324f, -0.1250f, -28.9375f, 30.0000f, 30, 31}, // 522a - {0.680176f, 0.604004f, 0.694336f, 0.619141f, 0.0625f, -28.6250f, 30.0000f, 29, 31}, // 522b + {0.357910f, 0.516113f, 0.372559f, 0.531250f, -0.3125f, -28.8125f, 30.0000f, 30, 31}, // 5229 + {0.630371f, 0.516113f, 0.645020f, 0.531250f, -0.1250f, -28.9375f, 30.0000f, 30, 31}, // 522a + {0.812500f, 0.636230f, 0.826660f, 0.651367f, 0.0625f, -28.6250f, 30.0000f, 29, 31}, // 522b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 522c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 522d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 522e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 522f - {0.076660f, 0.492676f, 0.091309f, 0.507813f, -0.0625f, -28.8125f, 30.0000f, 30, 31}, // 5230 + {0.770020f, 0.516113f, 0.784668f, 0.531250f, -0.0625f, -28.8125f, 30.0000f, 30, 31}, // 5230 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5231 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5232 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5233 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5234 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5235 - {0.235352f, 0.414551f, 0.250000f, 0.430176f, 0.3125f, -29.0625f, 30.0000f, 30, 32}, // 5236 - {0.185059f, 0.492676f, 0.199707f, 0.507813f, -0.2500f, -28.9375f, 30.0000f, 30, 31}, // 5237 - {0.206543f, 0.353516f, 0.221680f, 0.368652f, 0.0625f, -29.1250f, 30.0000f, 31, 31}, // 5238 + {0.679688f, 0.438965f, 0.694336f, 0.454590f, 0.3125f, -29.0625f, 30.0000f, 30, 32}, // 5236 + {0.785156f, 0.516113f, 0.799805f, 0.531250f, -0.2500f, -28.9375f, 30.0000f, 30, 31}, // 5237 + {0.080566f, 0.378418f, 0.095703f, 0.393555f, 0.0625f, -29.1250f, 30.0000f, 31, 31}, // 5238 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5239 - {0.391113f, 0.492676f, 0.405762f, 0.507813f, 0.0625f, -28.9375f, 30.0000f, 30, 31}, // 523a - {0.468750f, 0.492676f, 0.483398f, 0.507813f, -0.3750f, -28.8750f, 30.0000f, 30, 31}, // 523b + {0.661133f, 0.517578f, 0.675781f, 0.532715f, 0.0625f, -28.9375f, 30.0000f, 30, 31}, // 523a + {0.203125f, 0.518066f, 0.217773f, 0.533203f, -0.3750f, -28.8750f, 30.0000f, 30, 31}, // 523b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 523c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 523d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 523e @@ -2217,13 +2518,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5244 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5245 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5246 - {0.291504f, 0.553711f, 0.305664f, 0.569336f, -0.0625f, -28.9375f, 30.0000f, 29, 32}, // 5247 + {0.751953f, 0.578125f, 0.766113f, 0.593750f, -0.0625f, -28.9375f, 30.0000f, 29, 32}, // 5247 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5248 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5249 - {0.182129f, 0.604492f, 0.196289f, 0.619629f, 0.3750f, -29.0625f, 30.0000f, 29, 31}, // 524a + {0.660645f, 0.636719f, 0.674805f, 0.651855f, 0.3750f, -29.0625f, 30.0000f, 29, 31}, // 524a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 524b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 524c - {0.268066f, 0.414551f, 0.282715f, 0.430176f, 0.3125f, -29.5000f, 30.0000f, 30, 32}, // 524d + {0.763184f, 0.438965f, 0.777832f, 0.454590f, 0.3125f, -29.5000f, 30.0000f, 30, 32}, // 524d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 524e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 524f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5250 @@ -2232,12 +2533,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5253 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5254 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5255 - {0.320313f, 0.604492f, 0.334473f, 0.619629f, -0.1250f, -29.0000f, 30.0000f, 29, 31}, // 5256 + {0.967773f, 0.636719f, 0.981934f, 0.651855f, -0.1250f, -29.0000f, 30.0000f, 29, 31}, // 5256 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5257 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5258 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5259 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 525a - {0.848633f, 0.319824f, 0.862305f, 0.334961f, 1.0625f, -28.9375f, 30.0000f, 28, 31}, // 525b + {0.787109f, 0.683105f, 0.800781f, 0.698242f, 1.0625f, -28.9375f, 30.0000f, 28, 31}, // 525b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 525c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 525d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 525e @@ -2245,8 +2546,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5260 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5261 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5262 - {0.194824f, 0.191895f, 0.209961f, 0.207520f, -1.0000f, -29.3125f, 30.0000f, 31, 32}, // 5263 - {0.725586f, 0.492676f, 0.740234f, 0.507813f, -0.5000f, -28.8125f, 30.0000f, 30, 31}, // 5264 + {0.468750f, 0.209473f, 0.483887f, 0.225098f, -1.0000f, -29.3125f, 30.0000f, 31, 32}, // 5263 + {0.468262f, 0.518066f, 0.482910f, 0.533203f, -0.5000f, -28.8125f, 30.0000f, 30, 31}, // 5264 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5265 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5266 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5267 @@ -2257,13 +2558,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 526c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 526d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 526e - {0.331543f, 0.414551f, 0.346191f, 0.430176f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 526f - {0.222168f, 0.353516f, 0.237305f, 0.368652f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 5270 + {0.205566f, 0.439453f, 0.220215f, 0.455078f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 526f + {0.602051f, 0.378418f, 0.617188f, 0.393555f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 5270 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5271 - {0.740723f, 0.492676f, 0.755371f, 0.507813f, -0.2500f, -29.0000f, 30.0000f, 30, 31}, // 5272 + {0.515625f, 0.518066f, 0.530273f, 0.533203f, -0.2500f, -29.0000f, 30.0000f, 30, 31}, // 5272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5273 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5274 - {0.346680f, 0.414551f, 0.361328f, 0.430176f, -0.6250f, -29.2500f, 30.0000f, 30, 32}, // 5275 + {0.475098f, 0.439453f, 0.489746f, 0.455078f, -0.6250f, -29.2500f, 30.0000f, 30, 32}, // 5275 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5276 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5277 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5278 @@ -2281,7 +2582,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5284 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5285 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5286 - {0.659668f, 0.191895f, 0.674805f, 0.207520f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 5287 + {0.484375f, 0.209473f, 0.499512f, 0.225098f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 5287 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5288 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5289 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 528a @@ -2301,53 +2602,53 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5298 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5299 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 529a - {0.524902f, 0.397949f, 0.538574f, 0.413086f, 0.0625f, -28.7500f, 30.0000f, 28, 31}, // 529b + {0.801270f, 0.683105f, 0.814941f, 0.698242f, 0.0625f, -28.7500f, 30.0000f, 28, 31}, // 529b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 529c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 529d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 529e - {0.384766f, 0.553711f, 0.398926f, 0.569336f, 0.1875f, -28.7500f, 30.0000f, 29, 32}, // 529f - {0.617676f, 0.414551f, 0.632324f, 0.430176f, -0.3125f, -28.9375f, 30.0000f, 30, 32}, // 52a0 - {0.810547f, 0.048340f, 0.826172f, 0.063965f, -0.9375f, -28.9375f, 30.0000f, 32, 32}, // 52a1 + {0.654297f, 0.579102f, 0.668457f, 0.594727f, 0.1875f, -28.7500f, 30.0000f, 29, 32}, // 529f + {0.523926f, 0.439453f, 0.538574f, 0.455078f, -0.3125f, -28.9375f, 30.0000f, 30, 32}, // 52a0 + {0.498047f, 0.067871f, 0.513672f, 0.083496f, -0.9375f, -28.9375f, 30.0000f, 32, 32}, // 52a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52a2 - {0.833984f, 0.191895f, 0.849121f, 0.207520f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 52a3 + {0.500000f, 0.209473f, 0.515137f, 0.225098f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 52a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52a7 - {0.791992f, 0.492676f, 0.806641f, 0.507813f, -0.3750f, -28.9375f, 30.0000f, 30, 31}, // 52a8 - {0.147949f, 0.192383f, 0.163086f, 0.208008f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 52a9 - {0.399902f, 0.353516f, 0.415039f, 0.368652f, 0.0000f, -28.6875f, 30.0000f, 31, 31}, // 52aa + {0.562012f, 0.518066f, 0.576660f, 0.533203f, -0.3750f, -28.9375f, 30.0000f, 30, 31}, // 52a8 + {0.789551f, 0.209473f, 0.804688f, 0.225098f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 52a9 + {0.063965f, 0.378906f, 0.079102f, 0.394043f, 0.0000f, -28.6875f, 30.0000f, 31, 31}, // 52aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b0 - {0.460449f, 0.353516f, 0.475586f, 0.368652f, -1.1250f, -28.9375f, 30.0000f, 31, 31}, // 52b1 + {0.111328f, 0.378906f, 0.126465f, 0.394043f, -1.1250f, -28.9375f, 30.0000f, 31, 31}, // 52b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b3 - {0.653809f, 0.414551f, 0.668457f, 0.430176f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // 52b4 + {0.539063f, 0.439453f, 0.553711f, 0.455078f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // 52b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52b8 - {0.091797f, 0.493164f, 0.106445f, 0.508301f, 0.0000f, -29.0000f, 30.0000f, 30, 31}, // 52b9 + {0.029297f, 0.518555f, 0.043945f, 0.533691f, 0.0000f, -29.0000f, 30.0000f, 30, 31}, // 52b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52bd - {0.476074f, 0.353516f, 0.491211f, 0.368652f, -0.4375f, -28.9375f, 30.0000f, 31, 31}, // 52be + {0.159668f, 0.379395f, 0.174805f, 0.394531f, -0.4375f, -28.9375f, 30.0000f, 31, 31}, // 52be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c4 - {0.163574f, 0.192383f, 0.178711f, 0.208008f, -1.0625f, -29.1250f, 30.0000f, 31, 32}, // 52c5 + {0.337402f, 0.209961f, 0.352539f, 0.225586f, -1.0625f, -29.1250f, 30.0000f, 31, 32}, // 52c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c6 - {0.334961f, 0.606934f, 0.349121f, 0.622070f, -0.6875f, -28.3125f, 30.0000f, 29, 31}, // 52c7 + {0.982422f, 0.636719f, 0.996582f, 0.651855f, -0.6875f, -28.3125f, 30.0000f, 29, 31}, // 52c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52c8 - {0.543945f, 0.192871f, 0.559570f, 0.208008f, -0.8750f, -29.1250f, 30.0000f, 32, 31}, // 52c9 + {0.859375f, 0.210938f, 0.875000f, 0.226074f, -0.8750f, -29.1250f, 30.0000f, 32, 31}, // 52c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52cc @@ -2359,25 +2660,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52d4 - {0.702148f, 0.414551f, 0.716797f, 0.430176f, -0.2500f, -29.0000f, 30.0000f, 30, 32}, // 52d5 + {0.663574f, 0.439453f, 0.678223f, 0.455078f, -0.2500f, -29.0000f, 30.0000f, 30, 32}, // 52d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52d7 - {0.123047f, 0.493164f, 0.137695f, 0.508301f, -0.3750f, -28.8125f, 30.0000f, 30, 31}, // 52d8 - {0.847656f, 0.000000f, 0.863770f, 0.015625f, -0.9375f, -29.3750f, 30.0000f, 33, 32}, // 52d9 + {0.044434f, 0.518555f, 0.059082f, 0.533691f, -0.3750f, -28.8125f, 30.0000f, 30, 31}, // 52d8 + {0.688965f, 0.027832f, 0.705078f, 0.043457f, -0.9375f, -29.3750f, 30.0000f, 33, 32}, // 52d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52dc - {0.826660f, 0.048340f, 0.842285f, 0.063965f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 52dd + {0.514160f, 0.067871f, 0.529785f, 0.083496f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 52dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52de - {0.560059f, 0.192871f, 0.575684f, 0.208008f, -0.2500f, -29.1250f, 30.0000f, 32, 31}, // 52df + {0.370605f, 0.212402f, 0.386230f, 0.227539f, -0.2500f, -29.1250f, 30.0000f, 32, 31}, // 52df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e1 - {0.576172f, 0.192871f, 0.591797f, 0.208008f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 52e2 + {0.419434f, 0.212402f, 0.435059f, 0.227539f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 52e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e3 - {0.304199f, 0.355957f, 0.319336f, 0.371094f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 52e4 + {0.000000f, 0.379883f, 0.015137f, 0.395020f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 52e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e6 - {0.592285f, 0.192871f, 0.607422f, 0.208496f, -0.9375f, -29.2500f, 30.0000f, 31, 32}, // 52e7 + {0.435547f, 0.212402f, 0.450684f, 0.228027f, -0.9375f, -29.2500f, 30.0000f, 31, 32}, // 52e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ea @@ -2388,7 +2689,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f1 - {0.607910f, 0.192871f, 0.623047f, 0.208496f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 52f2 + {0.451172f, 0.212402f, 0.466309f, 0.228027f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 52f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f5 @@ -2396,18 +2697,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52f9 - {0.607422f, 0.553711f, 0.621582f, 0.569336f, 0.4375f, -29.5625f, 30.0000f, 29, 32}, // 52fa + {0.045410f, 0.579590f, 0.059570f, 0.595215f, 0.4375f, -29.5625f, 30.0000f, 29, 32}, // 52fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 52ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5300 - {0.368164f, 0.358398f, 0.383301f, 0.373535f, -0.8750f, -29.1250f, 30.0000f, 31, 31}, // 5301 + {0.015625f, 0.379883f, 0.030762f, 0.395020f, -0.8750f, -29.1250f, 30.0000f, 31, 31}, // 5301 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5302 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5303 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5304 - {0.623535f, 0.192871f, 0.639160f, 0.208008f, -0.6250f, -29.1875f, 30.0000f, 32, 31}, // 5305 + {0.548828f, 0.212402f, 0.564453f, 0.227539f, -0.6250f, -29.1875f, 30.0000f, 32, 31}, // 5305 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5306 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5307 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5308 @@ -2424,8 +2725,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5313 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5314 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5315 - {0.701172f, 0.192871f, 0.716797f, 0.208008f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5316 - {0.812500f, 0.414551f, 0.828125f, 0.429199f, -0.6875f, -27.8125f, 30.0000f, 32, 30}, // 5317 + {0.901855f, 0.212402f, 0.917480f, 0.227539f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5316 + {0.046875f, 0.439941f, 0.062500f, 0.454590f, -0.6875f, -27.8125f, 30.0000f, 32, 30}, // 5317 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5318 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5319 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 531a @@ -2434,7 +2735,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 531d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 531e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 531f - {0.075684f, 0.601563f, 0.089355f, 0.616211f, 1.8125f, -27.6875f, 30.0000f, 28, 30}, // 5320 + {0.858398f, 0.696289f, 0.872070f, 0.710938f, 1.8125f, -27.6875f, 30.0000f, 28, 30}, // 5320 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5321 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5322 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5323 @@ -2459,47 +2760,47 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5336 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5337 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5338 - {0.282227f, 0.676758f, 0.295898f, 0.690918f, 2.0000f, -26.3125f, 30.0000f, 28, 29}, // 5339 - {0.626465f, 0.645020f, 0.640625f, 0.659668f, 2.0000f, -27.5625f, 30.0000f, 29, 30}, // 533a - {0.739258f, 0.645020f, 0.753418f, 0.659668f, 1.0625f, -27.7500f, 30.0000f, 29, 30}, // 533b + {0.776855f, 0.713867f, 0.790527f, 0.728027f, 2.0000f, -26.3125f, 30.0000f, 28, 29}, // 5339 + {0.329590f, 0.672363f, 0.343750f, 0.687012f, 2.0000f, -27.5625f, 30.0000f, 29, 30}, // 533a + {0.452637f, 0.672363f, 0.466797f, 0.687012f, 1.0625f, -27.7500f, 30.0000f, 29, 30}, // 533b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 533c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 533d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 533e - {0.000000f, 0.608398f, 0.014160f, 0.623535f, 1.5000f, -28.0000f, 30.0000f, 29, 31}, // 533f + {0.242676f, 0.637207f, 0.256836f, 0.652344f, 1.5000f, -28.0000f, 30.0000f, 29, 31}, // 533f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5340 - {0.491211f, 0.050293f, 0.504883f, 0.065918f, 1.1250f, -29.1250f, 30.0000f, 28, 32}, // 5341 + {0.985840f, 0.447266f, 0.999512f, 0.462891f, 1.1250f, -29.1250f, 30.0000f, 28, 32}, // 5341 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5342 - {0.441895f, 0.648438f, 0.455566f, 0.663574f, 1.3750f, -28.9375f, 30.0000f, 28, 31}, // 5343 + {0.239258f, 0.683594f, 0.252930f, 0.698730f, 1.3750f, -28.9375f, 30.0000f, 28, 31}, // 5343 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5344 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5345 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5346 - {0.229980f, 0.493164f, 0.244629f, 0.508301f, 0.3750f, -28.8750f, 30.0000f, 30, 31}, // 5347 - {0.654297f, 0.553711f, 0.668457f, 0.569336f, 0.6875f, -29.0625f, 30.0000f, 29, 32}, // 5348 + {0.076660f, 0.518555f, 0.091309f, 0.533691f, 0.3750f, -28.8750f, 30.0000f, 30, 31}, // 5347 + {0.511719f, 0.579590f, 0.525879f, 0.595215f, 0.6875f, -29.0625f, 30.0000f, 29, 32}, // 5348 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5349 - {0.245117f, 0.493164f, 0.259766f, 0.508301f, 0.2500f, -28.7500f, 30.0000f, 30, 31}, // 534a + {0.184082f, 0.518555f, 0.198730f, 0.533691f, 0.2500f, -28.7500f, 30.0000f, 30, 31}, // 534a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 534b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 534c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 534d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 534e - {0.383789f, 0.358887f, 0.398926f, 0.374023f, -0.5000f, -29.0625f, 30.0000f, 31, 31}, // 534f + {0.126953f, 0.379883f, 0.142090f, 0.395020f, -0.5000f, -29.0625f, 30.0000f, 31, 31}, // 534f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5350 - {0.717285f, 0.192871f, 0.732422f, 0.208496f, -0.0625f, -29.4375f, 30.0000f, 31, 32}, // 5351 - {0.781250f, 0.414551f, 0.795898f, 0.430176f, 0.4375f, -29.1250f, 30.0000f, 30, 32}, // 5352 - {0.111816f, 0.359375f, 0.126953f, 0.374512f, -0.0625f, -28.8125f, 30.0000f, 31, 31}, // 5353 - {0.875000f, 0.414551f, 0.889648f, 0.430176f, -0.1250f, -29.1250f, 30.0000f, 30, 32}, // 5354 - {0.000000f, 0.360352f, 0.015137f, 0.375488f, -0.3750f, -29.2500f, 30.0000f, 31, 31}, // 5355 + {0.917969f, 0.212402f, 0.933105f, 0.228027f, -0.0625f, -29.4375f, 30.0000f, 31, 32}, // 5351 + {0.173340f, 0.439941f, 0.187988f, 0.455566f, 0.4375f, -29.1250f, 30.0000f, 30, 32}, // 5352 + {0.736328f, 0.380859f, 0.751465f, 0.395996f, -0.0625f, -28.8125f, 30.0000f, 31, 31}, // 5353 + {0.188477f, 0.439941f, 0.203125f, 0.455566f, -0.1250f, -29.1250f, 30.0000f, 30, 32}, // 5354 + {0.222168f, 0.381348f, 0.237305f, 0.396484f, -0.3750f, -29.2500f, 30.0000f, 31, 31}, // 5355 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5356 - {0.732910f, 0.192871f, 0.748047f, 0.208496f, 0.0000f, -28.9375f, 30.0000f, 31, 32}, // 5357 - {0.748535f, 0.192871f, 0.763672f, 0.208496f, -0.0625f, -29.6875f, 30.0000f, 31, 32}, // 5358 + {0.933594f, 0.212402f, 0.948730f, 0.228027f, 0.0000f, -28.9375f, 30.0000f, 31, 32}, // 5357 + {0.949219f, 0.212402f, 0.964355f, 0.228027f, -0.0625f, -29.6875f, 30.0000f, 31, 32}, // 5358 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5359 - {0.764160f, 0.192871f, 0.779297f, 0.208496f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 535a + {0.964844f, 0.212402f, 0.979980f, 0.228027f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 535a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 535b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 535c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 535d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 535e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 535f - {0.250488f, 0.674316f, 0.263184f, 0.689941f, 3.5000f, -29.0000f, 30.0000f, 26, 32}, // 5360 - {0.326660f, 0.493164f, 0.341309f, 0.508301f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 5361 + {0.145508f, 0.706055f, 0.158203f, 0.721680f, 3.5000f, -29.0000f, 30.0000f, 26, 32}, // 5360 + {0.483398f, 0.518555f, 0.498047f, 0.533691f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 5361 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5362 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5363 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5364 @@ -2514,15 +2815,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 536d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 536e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 536f - {0.176270f, 0.666504f, 0.189453f, 0.681641f, 2.4375f, -29.0625f, 30.0000f, 27, 31}, // 5370 - {0.779785f, 0.192871f, 0.794922f, 0.208496f, -0.1250f, -29.1250f, 30.0000f, 31, 32}, // 5371 + {0.070801f, 0.704590f, 0.083984f, 0.719727f, 2.4375f, -29.0625f, 30.0000f, 27, 31}, // 5370 + {0.980469f, 0.212402f, 0.995605f, 0.228027f, -0.1250f, -29.1250f, 30.0000f, 31, 32}, // 5371 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5372 - {0.698242f, 0.583496f, 0.712891f, 0.598145f, -0.3750f, -27.6250f, 30.0000f, 30, 30}, // 5373 - {0.502441f, 0.493164f, 0.517090f, 0.508301f, -0.5625f, -28.8125f, 30.0000f, 30, 31}, // 5374 - {0.104492f, 0.608398f, 0.118652f, 0.623535f, -0.2500f, -28.4375f, 30.0000f, 29, 31}, // 5375 + {0.335449f, 0.610352f, 0.350098f, 0.625000f, -0.3750f, -27.6250f, 30.0000f, 30, 30}, // 5373 + {0.610840f, 0.518555f, 0.625488f, 0.533691f, -0.5625f, -28.8125f, 30.0000f, 30, 31}, // 5374 + {0.425781f, 0.637207f, 0.439941f, 0.652344f, -0.2500f, -28.4375f, 30.0000f, 29, 31}, // 5375 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5376 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5377 - {0.076660f, 0.554199f, 0.090820f, 0.569824f, 0.1875f, -29.3750f, 30.0000f, 29, 32}, // 5378 + {0.559570f, 0.579590f, 0.573730f, 0.595215f, 0.1875f, -29.3750f, 30.0000f, 29, 32}, // 5378 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5379 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 537a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 537b @@ -2534,14 +2835,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5381 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5382 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5383 - {0.517578f, 0.493164f, 0.532715f, 0.507813f, -0.5625f, -27.3125f, 30.0000f, 31, 30}, // 5384 + {0.059570f, 0.519043f, 0.074707f, 0.533691f, -0.5625f, -27.3125f, 30.0000f, 31, 30}, // 5384 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5385 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5386 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5387 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5388 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5389 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 538a - {0.595215f, 0.493164f, 0.610352f, 0.507813f, -0.8750f, -27.1250f, 30.0000f, 31, 30}, // 538b + {0.123047f, 0.519043f, 0.138184f, 0.533691f, -0.8750f, -27.1250f, 30.0000f, 31, 30}, // 538b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 538c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 538d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 538e @@ -2554,14 +2855,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5395 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5396 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5397 - {0.626465f, 0.493164f, 0.641602f, 0.507813f, -0.6875f, -27.3750f, 30.0000f, 31, 30}, // 5398 + {0.530762f, 0.519043f, 0.545898f, 0.533691f, -0.6875f, -27.3750f, 30.0000f, 31, 30}, // 5398 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5399 - {0.015625f, 0.361816f, 0.030762f, 0.376953f, -0.5000f, -28.3125f, 30.0000f, 31, 31}, // 539a + {0.253906f, 0.381348f, 0.269043f, 0.396484f, -0.5000f, -28.3125f, 30.0000f, 31, 31}, // 539a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 539b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 539c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 539d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 539e - {0.773438f, 0.493164f, 0.788574f, 0.507813f, -0.2500f, -27.6250f, 30.0000f, 31, 30}, // 539f + {0.645508f, 0.519043f, 0.660645f, 0.533691f, -0.2500f, -27.6250f, 30.0000f, 31, 30}, // 539f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53a2 @@ -2581,7 +2882,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b2 - {0.890137f, 0.414551f, 0.904785f, 0.430176f, -1.0000f, -29.0625f, 30.0000f, 30, 32}, // 53b3 + {0.554199f, 0.439941f, 0.568848f, 0.455566f, -1.0000f, -29.0625f, 30.0000f, 30, 32}, // 53b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b6 @@ -2589,68 +2890,68 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53ba - {0.856445f, 0.493164f, 0.871094f, 0.508301f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 53bb + {0.138672f, 0.519531f, 0.153320f, 0.534668f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 53bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c1 - {0.864258f, 0.000000f, 0.880371f, 0.015625f, -1.4375f, -29.5000f, 30.0000f, 33, 32}, // 53c2 + {0.176758f, 0.028809f, 0.192871f, 0.044434f, -1.4375f, -29.5000f, 30.0000f, 33, 32}, // 53c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c7 - {0.373047f, 0.676758f, 0.387207f, 0.690430f, 0.8125f, -26.6250f, 30.0000f, 29, 28}, // 53c8 + {0.791016f, 0.713867f, 0.805176f, 0.727539f, 0.8125f, -26.6250f, 30.0000f, 29, 28}, // 53c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53c9 - {0.306152f, 0.554199f, 0.321777f, 0.568359f, -0.9375f, -27.0000f, 30.0000f, 32, 29}, // 53ca - {0.795410f, 0.192871f, 0.810547f, 0.208496f, -0.1875f, -29.3125f, 30.0000f, 31, 32}, // 53cb - {0.187500f, 0.415039f, 0.203125f, 0.429688f, -0.8750f, -27.1250f, 30.0000f, 32, 30}, // 53cc - {0.937988f, 0.493164f, 0.953125f, 0.507813f, -0.5000f, -27.7500f, 30.0000f, 31, 30}, // 53cd - {0.426758f, 0.415039f, 0.442383f, 0.429688f, -0.4375f, -28.5000f, 30.0000f, 32, 30}, // 53ce + {0.637695f, 0.579590f, 0.653320f, 0.593750f, -0.9375f, -27.0000f, 30.0000f, 32, 29}, // 53ca + {0.841309f, 0.212891f, 0.856445f, 0.228516f, -0.1875f, -29.3125f, 30.0000f, 31, 32}, // 53cb + {0.140625f, 0.440430f, 0.156250f, 0.455078f, -0.8750f, -27.1250f, 30.0000f, 32, 30}, // 53cc + {0.153809f, 0.519531f, 0.168945f, 0.534180f, -0.5000f, -27.7500f, 30.0000f, 31, 30}, // 53cd + {0.569336f, 0.440430f, 0.584961f, 0.455078f, -0.4375f, -28.5000f, 30.0000f, 32, 30}, // 53ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53d0 - {0.890137f, 0.192871f, 0.905762f, 0.208008f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 53d1 + {0.875488f, 0.213379f, 0.891113f, 0.228516f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 53d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53d3 - {0.906250f, 0.192871f, 0.921875f, 0.208008f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 53d4 + {0.113281f, 0.213867f, 0.128906f, 0.229004f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 53d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53d5 - {0.476074f, 0.415039f, 0.491699f, 0.429688f, -0.7500f, -27.3750f, 30.0000f, 32, 30}, // 53d6 - {0.047852f, 0.362305f, 0.062988f, 0.377441f, -0.1250f, -28.9375f, 30.0000f, 31, 31}, // 53d7 - {0.063477f, 0.362793f, 0.078613f, 0.377930f, -0.8750f, -29.0000f, 30.0000f, 31, 31}, // 53d8 - {0.842773f, 0.048340f, 0.858398f, 0.063965f, -1.5000f, -29.1250f, 30.0000f, 32, 32}, // 53d9 + {0.078125f, 0.440918f, 0.093750f, 0.455566f, -0.7500f, -27.3750f, 30.0000f, 32, 30}, // 53d6 + {0.719727f, 0.381348f, 0.734863f, 0.396484f, -0.1250f, -28.9375f, 30.0000f, 31, 31}, // 53d7 + {0.269531f, 0.381836f, 0.284668f, 0.396973f, -0.8750f, -29.0000f, 30.0000f, 31, 31}, // 53d8 + {0.608887f, 0.067871f, 0.624512f, 0.083496f, -1.5000f, -29.1250f, 30.0000f, 32, 32}, // 53d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53df - {0.953613f, 0.493164f, 0.968750f, 0.507813f, -0.3750f, -28.1875f, 30.0000f, 31, 30}, // 53e0 + {0.546387f, 0.519531f, 0.561523f, 0.534180f, -0.3750f, -28.1875f, 30.0000f, 31, 30}, // 53e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e2 - {0.316895f, 0.774414f, 0.328613f, 0.786621f, 3.5000f, -24.8750f, 30.0000f, 24, 25}, // 53e3 - {0.257324f, 0.611328f, 0.271484f, 0.626465f, 0.5000f, -28.6875f, 30.0000f, 29, 31}, // 53e4 - {0.969238f, 0.493164f, 0.983887f, 0.508301f, -0.0625f, -29.1875f, 30.0000f, 30, 31}, // 53e5 + {0.119141f, 0.844727f, 0.130859f, 0.856934f, 3.5000f, -24.8750f, 30.0000f, 24, 25}, // 53e3 + {0.440430f, 0.637207f, 0.454590f, 0.652344f, 0.5000f, -28.6875f, 30.0000f, 29, 31}, // 53e4 + {0.744141f, 0.520020f, 0.758789f, 0.535156f, -0.0625f, -29.1875f, 30.0000f, 30, 31}, // 53e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53e9 - {0.792480f, 0.611328f, 0.807617f, 0.625488f, -0.3125f, -27.1875f, 30.0000f, 31, 29}, // 53ea - {0.808105f, 0.611328f, 0.822266f, 0.626465f, 1.3750f, -28.9375f, 30.0000f, 29, 31}, // 53eb - {0.212891f, 0.601563f, 0.226563f, 0.616211f, 0.2500f, -27.6875f, 30.0000f, 28, 30}, // 53ec + {0.827148f, 0.637207f, 0.842285f, 0.651367f, -0.3125f, -27.1875f, 30.0000f, 31, 29}, // 53ea + {0.581055f, 0.637207f, 0.595215f, 0.652344f, 1.3750f, -28.9375f, 30.0000f, 29, 31}, // 53eb + {0.342773f, 0.697266f, 0.356445f, 0.711914f, 0.2500f, -27.6875f, 30.0000f, 28, 30}, // 53ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53ee - {0.815430f, 0.662109f, 0.829590f, 0.676270f, 0.9375f, -27.0625f, 30.0000f, 29, 29}, // 53ef - {0.409180f, 0.648926f, 0.422852f, 0.664063f, 1.6875f, -29.2500f, 30.0000f, 28, 31}, // 53f0 + {0.404785f, 0.693359f, 0.418945f, 0.707520f, 0.9375f, -27.0625f, 30.0000f, 29, 29}, // 53ef + {0.421387f, 0.683594f, 0.435059f, 0.698730f, 1.6875f, -29.2500f, 30.0000f, 28, 31}, // 53f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53f1 - {0.937988f, 0.192871f, 0.953125f, 0.208496f, -0.1250f, -29.0625f, 30.0000f, 31, 32}, // 53f2 - {0.984375f, 0.493164f, 0.999023f, 0.508301f, 0.0000f, -29.1250f, 30.0000f, 30, 31}, // 53f3 + {0.094727f, 0.214355f, 0.109863f, 0.229980f, -0.1250f, -29.0625f, 30.0000f, 31, 32}, // 53f2 + {0.262207f, 0.521484f, 0.276855f, 0.536621f, 0.0000f, -29.1250f, 30.0000f, 30, 31}, // 53f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53f6 - {0.138184f, 0.493652f, 0.153320f, 0.508301f, -0.0625f, -28.1875f, 30.0000f, 31, 30}, // 53f7 - {0.191895f, 0.662598f, 0.205566f, 0.677246f, 1.3125f, -27.6875f, 30.0000f, 28, 30}, // 53f8 + {0.232910f, 0.521973f, 0.248047f, 0.536621f, -0.0625f, -28.1875f, 30.0000f, 31, 30}, // 53f7 + {0.815430f, 0.697266f, 0.829102f, 0.711914f, 1.3125f, -27.6875f, 30.0000f, 28, 30}, // 53f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 53fb @@ -2662,50 +2963,50 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5401 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5402 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5403 - {0.499023f, 0.193359f, 0.514160f, 0.208984f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 5404 + {0.740723f, 0.214844f, 0.755859f, 0.230469f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 5404 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5405 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5406 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5407 - {0.880859f, 0.000000f, 0.896484f, 0.016113f, -0.8125f, -29.8125f, 30.0000f, 32, 33}, // 5408 - {0.374512f, 0.493652f, 0.389160f, 0.508789f, -0.1250f, -28.7500f, 30.0000f, 30, 31}, // 5409 + {0.193359f, 0.028809f, 0.208984f, 0.044922f, -0.8125f, -29.8125f, 30.0000f, 32, 33}, // 5408 + {0.577148f, 0.522461f, 0.591797f, 0.537598f, -0.1250f, -28.7500f, 30.0000f, 30, 31}, // 5409 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 540a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 540b - {0.041504f, 0.678223f, 0.054688f, 0.692871f, 1.5625f, -27.6250f, 30.0000f, 27, 30}, // 540c - {0.845703f, 0.129395f, 0.859375f, 0.145020f, -0.3750f, -29.1250f, 30.0000f, 28, 32}, // 540d - {0.811035f, 0.193359f, 0.826172f, 0.208984f, -0.6875f, -29.3750f, 30.0000f, 31, 32}, // 540e - {0.849609f, 0.193359f, 0.864746f, 0.208984f, 0.0625f, -28.7500f, 30.0000f, 31, 32}, // 540f - {0.167480f, 0.583984f, 0.182129f, 0.598633f, 0.9375f, -28.7500f, 30.0000f, 30, 30}, // 5410 - {0.504883f, 0.034180f, 0.518066f, 0.049805f, 1.9375f, -28.9375f, 30.0000f, 27, 32}, // 5411 + {0.267090f, 0.715820f, 0.280273f, 0.730469f, 1.5625f, -27.6250f, 30.0000f, 27, 30}, // 540c + {0.858398f, 0.649414f, 0.872070f, 0.665039f, -0.3750f, -29.1250f, 30.0000f, 28, 32}, // 540d + {0.386719f, 0.215332f, 0.401855f, 0.230957f, -0.6875f, -29.3750f, 30.0000f, 31, 32}, // 540e + {0.402344f, 0.215332f, 0.417480f, 0.230957f, 0.0625f, -28.7500f, 30.0000f, 31, 32}, // 540f + {0.634766f, 0.610352f, 0.649414f, 0.625000f, 0.9375f, -28.7500f, 30.0000f, 30, 30}, // 5410 + {0.240723f, 0.287109f, 0.253906f, 0.302734f, 1.9375f, -28.9375f, 30.0000f, 27, 32}, // 5411 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5412 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5413 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5414 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5415 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5416 - {0.880859f, 0.645020f, 0.895020f, 0.659668f, 1.0000f, -27.6875f, 30.0000f, 29, 30}, // 5417 + {0.619629f, 0.672363f, 0.633789f, 0.687012f, 1.0000f, -27.6875f, 30.0000f, 29, 30}, // 5417 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5418 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5419 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 541a - {0.250488f, 0.415527f, 0.266113f, 0.430176f, -0.6250f, -27.5000f, 30.0000f, 32, 30}, // 541b + {0.585449f, 0.440918f, 0.601074f, 0.455566f, -0.6250f, -27.5000f, 30.0000f, 32, 30}, // 541b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 541c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 541d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 541e - {0.203613f, 0.416016f, 0.218262f, 0.431641f, 0.6875f, -29.6250f, 30.0000f, 30, 32}, // 541f + {0.062988f, 0.441406f, 0.077637f, 0.457031f, 0.6875f, -29.6250f, 30.0000f, 30, 32}, // 541f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5420 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5421 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5422 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5423 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5424 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5425 - {0.218750f, 0.416016f, 0.234375f, 0.430664f, -0.6250f, -27.2500f, 30.0000f, 32, 30}, // 5426 - {0.895508f, 0.645020f, 0.910156f, 0.659180f, 0.8125f, -27.3750f, 30.0000f, 30, 29}, // 5427 + {0.108887f, 0.441406f, 0.124512f, 0.456055f, -0.6250f, -27.2500f, 30.0000f, 32, 30}, // 5426 + {0.733398f, 0.672363f, 0.748047f, 0.686523f, 0.8125f, -27.3750f, 30.0000f, 30, 29}, // 5427 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5428 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5429 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 542a - {0.858887f, 0.048340f, 0.874512f, 0.063965f, -0.9375f, -29.7500f, 30.0000f, 32, 32}, // 542b + {0.960938f, 0.067871f, 0.976563f, 0.083496f, -0.9375f, -29.7500f, 30.0000f, 32, 32}, // 542b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 542c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 542d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 542e - {0.214844f, 0.554199f, 0.229004f, 0.569824f, -0.6250f, -29.7500f, 30.0000f, 29, 32}, // 542f + {0.183594f, 0.580078f, 0.197754f, 0.595703f, -0.6250f, -29.7500f, 30.0000f, 29, 32}, // 542f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5430 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5431 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5432 @@ -2714,8 +3015,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5435 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5436 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5437 - {0.478516f, 0.583984f, 0.493164f, 0.598633f, 0.9375f, -27.6875f, 30.0000f, 30, 30}, // 5438 - {0.395508f, 0.416016f, 0.410156f, 0.431641f, 1.2500f, -29.1250f, 30.0000f, 30, 32}, // 5439 + {0.747070f, 0.610352f, 0.761719f, 0.625000f, 0.9375f, -27.6875f, 30.0000f, 30, 30}, // 5438 + {0.156738f, 0.441895f, 0.171387f, 0.457520f, 1.2500f, -29.1250f, 30.0000f, 30, 32}, // 5439 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 543a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 543b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 543c @@ -2730,9 +3031,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5445 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5446 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5447 - {0.589355f, 0.676758f, 0.603516f, 0.690430f, 0.3125f, -27.1875f, 30.0000f, 29, 28}, // 5448 - {0.406250f, 0.493652f, 0.421387f, 0.508301f, -0.4375f, -27.6250f, 30.0000f, 31, 30}, // 5449 - {0.442871f, 0.416016f, 0.457520f, 0.431641f, 0.0000f, -29.0000f, 30.0000f, 30, 32}, // 544a + {0.235840f, 0.714355f, 0.250000f, 0.728027f, 0.3125f, -27.1875f, 30.0000f, 29, 28}, // 5448 + {0.709473f, 0.522461f, 0.724609f, 0.537109f, -0.4375f, -27.6250f, 30.0000f, 31, 30}, // 5449 + {0.000000f, 0.442383f, 0.014648f, 0.458008f, 0.0000f, -29.0000f, 30.0000f, 30, 32}, // 544a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 544b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 544c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 544d @@ -2746,7 +3047,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5455 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5456 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5457 - {0.688965f, 0.662598f, 0.702637f, 0.677246f, 0.5000f, -27.3750f, 30.0000f, 28, 30}, // 5458 + {0.298828f, 0.697754f, 0.312500f, 0.712402f, 0.5000f, -27.3750f, 30.0000f, 28, 30}, // 5458 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5459 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 545a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 545b @@ -2762,7 +3063,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5465 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5466 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5467 - {0.542480f, 0.583984f, 0.557129f, 0.598633f, -0.8750f, -27.3750f, 30.0000f, 30, 30}, // 5468 + {0.197266f, 0.610840f, 0.211914f, 0.625488f, -0.8750f, -27.3750f, 30.0000f, 30, 30}, // 5468 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5469 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 546a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 546b @@ -2773,7 +3074,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5470 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5471 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5472 - {0.438477f, 0.493652f, 0.453125f, 0.508789f, 0.6875f, -28.9375f, 30.0000f, 30, 31}, // 5473 + {0.000000f, 0.522949f, 0.014648f, 0.538086f, 0.6875f, -28.9375f, 30.0000f, 30, 31}, // 5473 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5474 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5475 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5476 @@ -2782,8 +3083,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5479 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 547a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 547b - {0.030273f, 0.611816f, 0.044434f, 0.626953f, 0.9375f, -28.7500f, 30.0000f, 29, 31}, // 547c - {0.583496f, 0.000000f, 0.599609f, 0.016113f, -1.0625f, -29.8750f, 30.0000f, 33, 33}, // 547d + {0.921387f, 0.637207f, 0.935547f, 0.652344f, 0.9375f, -28.7500f, 30.0000f, 29, 31}, // 547c + {0.918457f, 0.019531f, 0.934570f, 0.035645f, -1.0625f, -29.8750f, 30.0000f, 33, 33}, // 547d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 547e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 547f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5480 @@ -2798,7 +3099,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5489 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 548a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 548b - {0.453613f, 0.493652f, 0.468262f, 0.508789f, -0.4375f, -28.6250f, 30.0000f, 30, 31}, // 548c + {0.218262f, 0.522949f, 0.232910f, 0.538086f, -0.4375f, -28.6250f, 30.0000f, 30, 31}, // 548c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 548d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 548e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 548f @@ -2836,7 +3137,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54b1 - {0.458008f, 0.416016f, 0.472656f, 0.431641f, 1.5625f, -29.1250f, 30.0000f, 30, 32}, // 54b2 + {0.015137f, 0.442383f, 0.029785f, 0.458008f, 1.5625f, -29.1250f, 30.0000f, 30, 32}, // 54b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54b5 @@ -2850,8 +3151,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54bf - {0.891113f, 0.048340f, 0.906738f, 0.063965f, -0.6250f, -29.0000f, 30.0000f, 32, 32}, // 54c0 - {0.750977f, 0.662598f, 0.764648f, 0.677246f, 1.4375f, -27.8125f, 30.0000f, 28, 30}, // 54c1 + {0.977051f, 0.067871f, 0.992676f, 0.083496f, -0.6250f, -29.0000f, 30.0000f, 32, 32}, // 54c0 + {0.984375f, 0.697754f, 0.998047f, 0.712402f, 1.4375f, -27.8125f, 30.0000f, 28, 30}, // 54c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54c4 @@ -2883,7 +3184,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54e0 - {0.888672f, 0.493652f, 0.903809f, 0.508301f, -0.1875f, -27.5625f, 30.0000f, 31, 30}, // 54e1 + {0.406738f, 0.522949f, 0.421875f, 0.537598f, -0.1875f, -27.5625f, 30.0000f, 31, 30}, // 54e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54e4 @@ -2900,7 +3201,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54f1 - {0.918945f, 0.493652f, 0.933594f, 0.508789f, -0.1250f, -28.7500f, 30.0000f, 30, 31}, // 54f2 + {0.422363f, 0.522949f, 0.437012f, 0.538086f, -0.1250f, -28.7500f, 30.0000f, 30, 31}, // 54f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 54f5 @@ -2920,8 +3221,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5503 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5504 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5505 - {0.299316f, 0.418457f, 0.313965f, 0.434082f, 1.0000f, -29.5000f, 30.0000f, 30, 32}, // 5506 - {0.260254f, 0.494141f, 0.275391f, 0.508789f, -0.4375f, -27.6250f, 30.0000f, 31, 30}, // 5507 + {0.125000f, 0.442383f, 0.139648f, 0.458008f, 1.0000f, -29.5000f, 30.0000f, 30, 32}, // 5506 + {0.693848f, 0.522949f, 0.708984f, 0.537598f, -0.4375f, -27.6250f, 30.0000f, 31, 30}, // 5507 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5508 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5509 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 550a @@ -2930,7 +3231,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 550d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 550e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 550f - {0.865234f, 0.193359f, 0.880371f, 0.208984f, -0.7500f, -29.1250f, 30.0000f, 31, 32}, // 5510 + {0.643066f, 0.215820f, 0.658203f, 0.231445f, -0.7500f, -29.1250f, 30.0000f, 31, 32}, // 5510 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5511 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5512 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5513 @@ -2961,9 +3262,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 552c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 552d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 552e - {0.361816f, 0.420898f, 0.376465f, 0.436523f, 0.8750f, -29.0625f, 30.0000f, 30, 32}, // 552f + {0.730957f, 0.443359f, 0.745605f, 0.458984f, 0.8750f, -29.0625f, 30.0000f, 30, 32}, // 552f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5530 - {0.830078f, 0.662598f, 0.843750f, 0.677246f, 1.4375f, -27.6250f, 30.0000f, 28, 30}, // 5531 + {0.784668f, 0.698730f, 0.798340f, 0.713379f, 1.4375f, -27.6250f, 30.0000f, 28, 30}, // 5531 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5532 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5533 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5534 @@ -2984,7 +3285,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5543 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5544 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5545 - {0.031250f, 0.363281f, 0.046387f, 0.378418f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 5546 + {0.237793f, 0.382813f, 0.252930f, 0.397949f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 5546 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5547 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5548 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5549 @@ -2993,11 +3294,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 554c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 554d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 554e - {0.924805f, 0.662598f, 0.938477f, 0.677246f, 1.5625f, -27.5625f, 30.0000f, 28, 30}, // 554f + {0.798828f, 0.698730f, 0.812500f, 0.713379f, 1.5625f, -27.5625f, 30.0000f, 28, 30}, // 554f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5550 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5551 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5552 - {0.922363f, 0.193359f, 0.937988f, 0.208496f, -0.3750f, -29.1875f, 30.0000f, 32, 31}, // 5553 + {0.682129f, 0.216797f, 0.697754f, 0.231934f, -0.3750f, -29.1875f, 30.0000f, 32, 31}, // 5553 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5554 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5555 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5556 @@ -3009,7 +3310,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 555c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 555d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 555e - {0.896973f, 0.000000f, 0.913086f, 0.015625f, -1.0000f, -29.0625f, 30.0000f, 33, 32}, // 555f + {0.209473f, 0.028809f, 0.225586f, 0.044434f, -1.0000f, -29.0625f, 30.0000f, 33, 32}, // 555f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5560 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5561 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5562 @@ -3046,7 +3347,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5581 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5582 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5583 - {0.376953f, 0.421387f, 0.391602f, 0.437012f, -0.3125f, -29.0625f, 30.0000f, 30, 32}, // 5584 + {0.220703f, 0.443848f, 0.235352f, 0.459473f, -0.3125f, -29.0625f, 30.0000f, 30, 32}, // 5584 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5585 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5586 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5587 @@ -3068,10 +3369,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5597 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5598 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5599 - {0.953613f, 0.193359f, 0.968750f, 0.208984f, 0.3125f, -29.1875f, 30.0000f, 31, 32}, // 559a + {0.353027f, 0.217285f, 0.368164f, 0.232910f, 0.3125f, -29.1875f, 30.0000f, 31, 32}, // 559a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 559b - {0.694824f, 0.494141f, 0.709473f, 0.509277f, 0.5625f, -29.1250f, 30.0000f, 30, 31}, // 559c - {0.660156f, 0.645508f, 0.674316f, 0.660156f, 1.1250f, -28.0000f, 30.0000f, 29, 30}, // 559d + {0.725098f, 0.522949f, 0.739746f, 0.538086f, 0.5625f, -29.1250f, 30.0000f, 30, 31}, // 559c + {0.117676f, 0.672852f, 0.131836f, 0.687500f, 1.1250f, -28.0000f, 30.0000f, 29, 30}, // 559d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 559e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 559f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55a0 @@ -3084,11 +3385,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55a9 - {0.969238f, 0.193359f, 0.984375f, 0.208984f, 0.2500f, -28.8750f, 30.0000f, 31, 32}, // 55aa - {0.871582f, 0.494141f, 0.886230f, 0.509277f, 0.8750f, -29.0625f, 30.0000f, 30, 31}, // 55ab + {0.805176f, 0.217285f, 0.820313f, 0.232910f, 0.2500f, -28.8750f, 30.0000f, 31, 32}, // 55aa + {0.169434f, 0.523438f, 0.184082f, 0.538574f, 0.8750f, -29.0625f, 30.0000f, 30, 31}, // 55ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55ad - {0.200195f, 0.495117f, 0.215332f, 0.509766f, -0.3750f, -27.6875f, 30.0000f, 31, 30}, // 55ae + {0.437500f, 0.523438f, 0.452637f, 0.538086f, -0.3750f, -27.6875f, 30.0000f, 31, 30}, // 55ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b1 @@ -3096,7 +3397,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b5 - {0.044922f, 0.611816f, 0.059082f, 0.626953f, 0.8125f, -29.0625f, 30.0000f, 29, 31}, // 55b6 + {0.777344f, 0.637695f, 0.791504f, 0.652832f, 0.8125f, -29.0625f, 30.0000f, 29, 31}, // 55b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55b9 @@ -3120,7 +3421,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55cd - {0.163086f, 0.645996f, 0.177246f, 0.660645f, 1.1250f, -27.5000f, 30.0000f, 29, 30}, // 55ce + {0.494141f, 0.672852f, 0.508301f, 0.687500f, 1.1250f, -27.5000f, 30.0000f, 29, 30}, // 55ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55d1 @@ -3141,7 +3442,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e2 - {0.938965f, 0.662598f, 0.952637f, 0.677246f, 1.3125f, -27.6250f, 30.0000f, 28, 30}, // 55e3 + {0.238281f, 0.699219f, 0.251953f, 0.713867f, 1.3125f, -27.6250f, 30.0000f, 28, 30}, // 55e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 55e6 @@ -3176,7 +3477,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5603 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5604 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5605 - {0.385254f, 0.193848f, 0.400391f, 0.209473f, 0.5000f, -29.0000f, 30.0000f, 31, 32}, // 5606 + {0.820801f, 0.217285f, 0.835938f, 0.232910f, 0.5000f, -29.0000f, 30.0000f, 31, 32}, // 5606 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5607 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5608 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5609 @@ -3219,7 +3520,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 562e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 562f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5630 - {0.394531f, 0.645996f, 0.408691f, 0.660645f, 0.6875f, -27.4375f, 30.0000f, 29, 30}, // 5631 + {0.177734f, 0.673340f, 0.191895f, 0.687988f, 0.6875f, -27.4375f, 30.0000f, 29, 30}, // 5631 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5632 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5633 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5634 @@ -3274,7 +3575,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5665 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5666 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5667 - {0.109375f, 0.421875f, 0.125000f, 0.436523f, -0.5625f, -27.9375f, 30.0000f, 32, 30}, // 5668 + {0.251953f, 0.443848f, 0.267578f, 0.458496f, -0.5625f, -27.9375f, 30.0000f, 32, 30}, // 5668 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5669 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 566a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 566b @@ -3286,7 +3587,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5671 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5672 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5673 - {0.514648f, 0.193848f, 0.529785f, 0.209473f, 0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5674 + {0.208984f, 0.218750f, 0.224121f, 0.234375f, 0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5674 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5675 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5676 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5677 @@ -3305,7 +3606,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5684 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5685 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5686 - {0.639648f, 0.193848f, 0.654785f, 0.209473f, 0.4375f, -29.0625f, 30.0000f, 31, 32}, // 5687 + {0.224609f, 0.218750f, 0.239746f, 0.234375f, 0.4375f, -29.0625f, 30.0000f, 31, 32}, // 5687 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5688 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5689 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 568a @@ -3388,16 +3689,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56d9 - {0.118652f, 0.678223f, 0.131836f, 0.692871f, 1.9375f, -27.3125f, 30.0000f, 27, 30}, // 56da - {0.051758f, 0.706055f, 0.064941f, 0.719727f, 1.6250f, -26.3125f, 30.0000f, 27, 28}, // 56db + {0.054688f, 0.716309f, 0.067871f, 0.730957f, 1.9375f, -27.3125f, 30.0000f, 27, 30}, // 56da + {0.010742f, 0.749023f, 0.023926f, 0.762695f, 1.6250f, -26.3125f, 30.0000f, 27, 28}, // 56db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56dd - {0.200195f, 0.706055f, 0.213379f, 0.719727f, 1.8750f, -26.6250f, 30.0000f, 27, 28}, // 56de + {0.314453f, 0.749023f, 0.327637f, 0.762695f, 1.8750f, -26.6250f, 30.0000f, 27, 28}, // 56de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56df - {0.220215f, 0.678223f, 0.233398f, 0.692871f, 1.8750f, -27.8125f, 30.0000f, 27, 30}, // 56e0 + {0.739746f, 0.716309f, 0.752930f, 0.730957f, 1.8750f, -27.8125f, 30.0000f, 27, 30}, // 56e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56e1 - {0.345215f, 0.678223f, 0.358398f, 0.692871f, 1.2500f, -27.5625f, 30.0000f, 27, 30}, // 56e2 - {0.358887f, 0.678223f, 0.372070f, 0.692871f, 1.6250f, -27.5625f, 30.0000f, 27, 30}, // 56e3 + {0.280762f, 0.716797f, 0.293945f, 0.731445f, 1.2500f, -27.5625f, 30.0000f, 27, 30}, // 56e2 + {0.084473f, 0.717285f, 0.097656f, 0.731934f, 1.6250f, -27.5625f, 30.0000f, 27, 30}, // 56e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56e6 @@ -3410,21 +3711,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56ef - {0.042480f, 0.663086f, 0.056152f, 0.677734f, 1.3750f, -27.5625f, 30.0000f, 28, 30}, // 56f0 + {0.419434f, 0.699219f, 0.433105f, 0.713867f, 1.3750f, -27.5625f, 30.0000f, 28, 30}, // 56f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f1 - {0.604004f, 0.678223f, 0.617188f, 0.692871f, 1.6250f, -27.6875f, 30.0000f, 27, 30}, // 56f2 - {0.636230f, 0.678223f, 0.649414f, 0.692871f, 1.6250f, -27.4375f, 30.0000f, 27, 30}, // 56f3 + {0.971191f, 0.717285f, 0.984375f, 0.731934f, 1.6250f, -27.6875f, 30.0000f, 27, 30}, // 56f2 + {0.705566f, 0.718262f, 0.718750f, 0.732910f, 1.6250f, -27.4375f, 30.0000f, 27, 30}, // 56f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56f9 - {0.118652f, 0.663086f, 0.132324f, 0.677734f, 1.4375f, -27.5625f, 30.0000f, 28, 30}, // 56fa + {0.433594f, 0.699219f, 0.447266f, 0.713867f, 1.4375f, -27.5625f, 30.0000f, 28, 30}, // 56fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56fc - {0.858398f, 0.678223f, 0.871582f, 0.692871f, 1.6250f, -27.6875f, 30.0000f, 27, 30}, // 56fd - {0.950684f, 0.678223f, 0.963867f, 0.692871f, 1.3125f, -27.5625f, 30.0000f, 27, 30}, // 56fe + {0.325684f, 0.718750f, 0.338867f, 0.733398f, 1.6250f, -27.6875f, 30.0000f, 27, 30}, // 56fd + {0.447754f, 0.718750f, 0.460938f, 0.733398f, 1.3125f, -27.5625f, 30.0000f, 27, 30}, // 56fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 56ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5700 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5701 @@ -3437,18 +3738,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5708 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5709 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 570a - {0.222168f, 0.663086f, 0.235840f, 0.677734f, 1.2500f, -27.3750f, 30.0000f, 28, 30}, // 570b + {0.565430f, 0.699219f, 0.579102f, 0.713867f, 1.2500f, -27.3750f, 30.0000f, 28, 30}, // 570b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 570c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 570d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 570e - {0.344727f, 0.663086f, 0.358398f, 0.677734f, 1.1875f, -27.5625f, 30.0000f, 28, 30}, // 570f + {0.645996f, 0.699219f, 0.659668f, 0.713867f, 1.1875f, -27.5625f, 30.0000f, 28, 30}, // 570f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5710 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5711 - {0.358887f, 0.663086f, 0.372559f, 0.677734f, 1.0625f, -27.7500f, 30.0000f, 28, 30}, // 5712 + {0.829590f, 0.699219f, 0.843262f, 0.713867f, 1.0625f, -27.7500f, 30.0000f, 28, 30}, // 5712 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5713 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5714 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5715 - {0.605957f, 0.663086f, 0.619629f, 0.677734f, 1.5625f, -27.8125f, 30.0000f, 28, 30}, // 5716 + {0.890137f, 0.699219f, 0.903809f, 0.713867f, 1.5625f, -27.8125f, 30.0000f, 28, 30}, // 5716 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5717 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5718 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5719 @@ -3457,16 +3758,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 571c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 571d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 571e - {0.470215f, 0.645996f, 0.484863f, 0.660156f, 0.3125f, -28.3125f, 30.0000f, 30, 29}, // 571f + {0.634277f, 0.673340f, 0.648926f, 0.687500f, 0.3125f, -28.3125f, 30.0000f, 30, 29}, // 571f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5720 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5721 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5722 - {0.151367f, 0.611816f, 0.166504f, 0.625977f, -0.1875f, -27.2500f, 30.0000f, 31, 29}, // 5723 + {0.842773f, 0.637695f, 0.857910f, 0.651855f, -0.1875f, -27.2500f, 30.0000f, 31, 29}, // 5723 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5724 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5725 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5726 - {0.295410f, 0.496582f, 0.310547f, 0.511230f, -0.9375f, -27.1250f, 30.0000f, 31, 30}, // 5727 - {0.272949f, 0.194336f, 0.288086f, 0.209961f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5728 + {0.833496f, 0.524414f, 0.848633f, 0.539063f, -0.9375f, -27.1250f, 30.0000f, 31, 30}, // 5727 + {0.240234f, 0.218750f, 0.255371f, 0.234375f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 5728 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5729 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 572a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 572b @@ -3474,7 +3775,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 572d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 572e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 572f - {0.341797f, 0.499023f, 0.356934f, 0.513672f, -0.3750f, -28.2500f, 30.0000f, 31, 30}, // 5730 + {0.498535f, 0.524902f, 0.513672f, 0.539551f, -0.3750f, -28.2500f, 30.0000f, 31, 30}, // 5730 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5731 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5732 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5733 @@ -3490,24 +3791,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 573d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 573e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 573f - {0.514160f, 0.554199f, 0.529785f, 0.568359f, -0.6875f, -27.6250f, 30.0000f, 32, 29}, // 5740 + {0.198242f, 0.580078f, 0.213867f, 0.594238f, -0.6875f, -27.6250f, 30.0000f, 32, 29}, // 5740 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5741 - {0.000000f, 0.422852f, 0.015625f, 0.437500f, -0.7500f, -27.5625f, 30.0000f, 32, 30}, // 5742 + {0.711914f, 0.443848f, 0.727539f, 0.458496f, -0.7500f, -27.5625f, 30.0000f, 32, 30}, // 5742 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5743 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5744 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5745 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5746 - {0.357422f, 0.499023f, 0.372070f, 0.514160f, -0.5625f, -28.9375f, 30.0000f, 30, 31}, // 5747 + {0.800293f, 0.524902f, 0.814941f, 0.540039f, -0.5625f, -28.9375f, 30.0000f, 30, 31}, // 5747 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5748 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5749 - {0.907227f, 0.048340f, 0.922852f, 0.063965f, -0.8125f, -28.8750f, 30.0000f, 32, 32}, // 574a + {0.901367f, 0.068359f, 0.916992f, 0.083984f, -0.8125f, -28.8750f, 30.0000f, 32, 32}, // 574a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 574b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 574c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 574d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 574e - {0.046875f, 0.424805f, 0.062500f, 0.439453f, -0.8125f, -27.7500f, 30.0000f, 32, 30}, // 574f - {0.557617f, 0.583984f, 0.572266f, 0.598633f, 0.1875f, -28.1875f, 30.0000f, 30, 30}, // 5750 - {0.288574f, 0.194336f, 0.304199f, 0.209473f, -0.6250f, -28.4375f, 30.0000f, 32, 31}, // 5751 + {0.268066f, 0.444336f, 0.283691f, 0.458984f, -0.8125f, -27.7500f, 30.0000f, 32, 30}, // 574f + {0.059570f, 0.611328f, 0.074219f, 0.625977f, 0.1875f, -28.1875f, 30.0000f, 30, 30}, // 5750 + {0.515625f, 0.218750f, 0.531250f, 0.233887f, -0.6250f, -28.4375f, 30.0000f, 32, 31}, // 5751 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5752 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5753 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5754 @@ -3517,7 +3818,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5758 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5759 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 575a - {0.106934f, 0.500000f, 0.122070f, 0.514648f, -0.7500f, -28.5000f, 30.0000f, 31, 30}, // 575b + {0.917480f, 0.524902f, 0.932617f, 0.539551f, -0.7500f, -28.5000f, 30.0000f, 31, 30}, // 575b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 575c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 575d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 575e @@ -3532,7 +3833,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5767 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5768 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5769 - {0.000000f, 0.500977f, 0.015137f, 0.515625f, -0.5000f, -27.8750f, 30.0000f, 31, 30}, // 576a + {0.933105f, 0.524902f, 0.948242f, 0.539551f, -0.5000f, -27.8750f, 30.0000f, 31, 30}, // 576a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 576b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 576c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 576d @@ -3556,7 +3857,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 577f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5780 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5781 - {0.572754f, 0.583984f, 0.587402f, 0.598633f, 0.1875f, -28.8125f, 30.0000f, 30, 30}, // 5782 + {0.456055f, 0.611328f, 0.470703f, 0.625977f, 0.1875f, -28.8125f, 30.0000f, 30, 30}, // 5782 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5783 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5784 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5785 @@ -3565,7 +3866,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5788 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5789 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 578a - {0.015625f, 0.502441f, 0.030762f, 0.517090f, -0.2500f, -28.8125f, 30.0000f, 31, 30}, // 578b + {0.967285f, 0.525391f, 0.982422f, 0.540039f, -0.2500f, -28.8125f, 30.0000f, 31, 30}, // 578b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 578c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 578d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 578e @@ -3589,7 +3890,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a2 - {0.183594f, 0.554688f, 0.199219f, 0.568848f, -0.6250f, -28.2500f, 30.0000f, 32, 29}, // 57a3 + {0.060059f, 0.580566f, 0.075684f, 0.594727f, -0.6250f, -28.2500f, 30.0000f, 32, 29}, // 57a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57a6 @@ -3629,10 +3930,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57ca - {0.399414f, 0.554688f, 0.415039f, 0.568848f, -0.8750f, -27.8750f, 30.0000f, 32, 29}, // 57cb + {0.460938f, 0.580566f, 0.476563f, 0.594727f, -0.8750f, -27.8750f, 30.0000f, 32, 29}, // 57cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57cd - {0.923340f, 0.048340f, 0.938965f, 0.063965f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 57ce + {0.941406f, 0.068848f, 0.957031f, 0.084473f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 57ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57d1 @@ -3649,7 +3950,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57de - {0.939453f, 0.048340f, 0.955078f, 0.063965f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 57df + {0.111816f, 0.069824f, 0.127441f, 0.085449f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 57df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57e2 @@ -3673,21 +3974,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57f6 - {0.955566f, 0.048340f, 0.971191f, 0.063965f, -0.3125f, -29.0000f, 30.0000f, 32, 32}, // 57f7 + {0.127930f, 0.069824f, 0.143555f, 0.085449f, -0.3125f, -29.0000f, 30.0000f, 32, 32}, // 57f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57f8 - {0.971680f, 0.048340f, 0.987305f, 0.063965f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 57f9 - {0.720703f, 0.350586f, 0.736816f, 0.365234f, -0.9375f, -29.0000f, 30.0000f, 33, 30}, // 57fa + {0.144043f, 0.070313f, 0.159668f, 0.085938f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 57f9 + {0.416504f, 0.370605f, 0.432617f, 0.385254f, -0.9375f, -29.0000f, 30.0000f, 33, 30}, // 57fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 57ff - {0.045898f, 0.502441f, 0.060547f, 0.517578f, -0.6250f, -28.5625f, 30.0000f, 30, 31}, // 5800 + {0.277344f, 0.525879f, 0.291992f, 0.541016f, -0.6250f, -28.5625f, 30.0000f, 30, 31}, // 5800 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5801 - {0.634766f, 0.583984f, 0.649414f, 0.598633f, 0.5000f, -29.0000f, 30.0000f, 30, 30}, // 5802 + {0.649902f, 0.611328f, 0.664551f, 0.625977f, 0.5000f, -29.0000f, 30.0000f, 30, 30}, // 5802 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5803 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5804 - {0.014648f, 0.613281f, 0.029785f, 0.627441f, -0.3750f, -27.5625f, 30.0000f, 31, 29}, // 5805 + {0.318848f, 0.638184f, 0.333984f, 0.652344f, -0.3750f, -27.5625f, 30.0000f, 31, 29}, // 5805 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5806 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5807 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5808 @@ -3703,7 +4004,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5812 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5813 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5814 - {0.893066f, 0.583984f, 0.907715f, 0.598633f, -0.2500f, -28.8750f, 30.0000f, 30, 30}, // 5815 + {0.044434f, 0.611816f, 0.059082f, 0.626465f, -0.2500f, -28.8750f, 30.0000f, 30, 30}, // 5815 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5816 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5817 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5818 @@ -3718,23 +4019,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5821 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5822 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5823 - {0.016113f, 0.425781f, 0.031738f, 0.440430f, -0.5625f, -27.8125f, 30.0000f, 32, 30}, // 5824 + {0.235840f, 0.445313f, 0.251465f, 0.459961f, -0.5625f, -27.8125f, 30.0000f, 32, 30}, // 5824 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5825 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5826 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5827 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5828 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5829 - {0.304688f, 0.194336f, 0.320313f, 0.209473f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 582a + {0.531738f, 0.218750f, 0.547363f, 0.233887f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 582a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 582b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 582c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 582d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 582e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 582f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5830 - {0.450684f, 0.194336f, 0.466309f, 0.209473f, -0.0625f, -29.0000f, 30.0000f, 32, 31}, // 5831 + {0.564941f, 0.219727f, 0.580566f, 0.234863f, -0.0625f, -29.0000f, 30.0000f, 32, 31}, // 5831 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5832 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5833 - {0.283203f, 0.426758f, 0.298828f, 0.441406f, -0.7500f, -27.6875f, 30.0000f, 32, 30}, // 5834 + {0.030273f, 0.445801f, 0.045898f, 0.460449f, -0.7500f, -27.6875f, 30.0000f, 32, 30}, // 5834 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5835 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5836 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5837 @@ -3746,8 +4047,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 583d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 583e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 583f - {0.466797f, 0.194824f, 0.482422f, 0.209961f, -0.8125f, -28.1250f, 30.0000f, 32, 31}, // 5840 - {0.275879f, 0.503418f, 0.291016f, 0.518066f, -0.3750f, -28.4375f, 30.0000f, 31, 30}, // 5841 + {0.581055f, 0.219727f, 0.596680f, 0.234863f, -0.8125f, -28.1250f, 30.0000f, 32, 31}, // 5840 + {0.948730f, 0.525879f, 0.963867f, 0.540527f, -0.3750f, -28.4375f, 30.0000f, 31, 30}, // 5841 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5842 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5843 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5844 @@ -3756,23 +4057,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5847 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5848 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5849 - {0.566406f, 0.048828f, 0.582031f, 0.064453f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 584a + {0.787109f, 0.070313f, 0.802734f, 0.085938f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 584a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 584b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 584c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 584d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 584e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 584f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5850 - {0.061035f, 0.503906f, 0.076172f, 0.518555f, -0.4375f, -29.0000f, 30.0000f, 31, 30}, // 5851 + {0.453125f, 0.526367f, 0.468262f, 0.541016f, -0.4375f, -29.0000f, 30.0000f, 31, 30}, // 5851 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5852 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5853 - {0.433105f, 0.195313f, 0.448730f, 0.210449f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 5854 + {0.658691f, 0.219727f, 0.674316f, 0.234863f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 5854 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5855 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5856 - {0.675293f, 0.195313f, 0.690918f, 0.210449f, -0.6875f, -29.6875f, 30.0000f, 32, 31}, // 5857 + {0.698242f, 0.219727f, 0.713867f, 0.234863f, -0.6875f, -29.6875f, 30.0000f, 32, 31}, // 5857 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5858 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5859 - {0.322266f, 0.171387f, 0.338379f, 0.186523f, -0.9375f, -28.2500f, 30.0000f, 33, 31}, // 585a + {0.000000f, 0.191406f, 0.016113f, 0.206543f, -0.9375f, -28.2500f, 30.0000f, 33, 31}, // 585a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 585b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 585c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 585d @@ -3787,7 +4088,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5866 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5867 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5868 - {0.828613f, 0.426758f, 0.844238f, 0.441406f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 5869 + {0.424805f, 0.445801f, 0.440430f, 0.460449f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 5869 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 586a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 586b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 586c @@ -3808,12 +4109,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 587b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 587c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 587d - {0.156250f, 0.427734f, 0.171875f, 0.442383f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 587e + {0.440918f, 0.445801f, 0.456543f, 0.460449f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 587e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 587f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5880 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5881 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5882 - {0.482910f, 0.195801f, 0.498535f, 0.210938f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 5883 + {0.714355f, 0.219727f, 0.729980f, 0.234863f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 5883 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5884 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5885 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5886 @@ -3829,16 +4130,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5890 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5891 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5892 - {0.210449f, 0.196289f, 0.226074f, 0.211426f, -0.6875f, -29.0000f, 30.0000f, 32, 31}, // 5893 + {0.047852f, 0.220703f, 0.063477f, 0.235840f, -0.6875f, -29.0000f, 30.0000f, 32, 31}, // 5893 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5894 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5895 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5896 - {0.226563f, 0.196777f, 0.241699f, 0.212402f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 5897 + {0.063965f, 0.220703f, 0.079102f, 0.236328f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 5897 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5898 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5899 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 589a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 589b - {0.242188f, 0.196777f, 0.257813f, 0.211914f, -0.2500f, -29.4375f, 30.0000f, 32, 31}, // 589c + {0.597168f, 0.221191f, 0.612793f, 0.236328f, -0.2500f, -29.4375f, 30.0000f, 32, 31}, // 589c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 589d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 589e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 589f @@ -3850,7 +4151,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58a7 - {0.825195f, 0.503906f, 0.840332f, 0.518555f, -0.3125f, -28.5000f, 30.0000f, 31, 30}, // 58a8 + {0.894043f, 0.526855f, 0.909180f, 0.541504f, -0.3125f, -28.5000f, 30.0000f, 31, 30}, // 58a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ab @@ -3861,7 +4162,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b2 - {0.699219f, 0.048828f, 0.714844f, 0.064453f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 58b3 + {0.423828f, 0.070801f, 0.439453f, 0.086426f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 58b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58b6 @@ -3872,28 +4173,28 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58bd - {0.153809f, 0.504395f, 0.168945f, 0.519043f, -0.1250f, -28.8750f, 30.0000f, 31, 30}, // 58be + {0.391602f, 0.527344f, 0.406738f, 0.541992f, -0.1250f, -28.8750f, 30.0000f, 31, 30}, // 58be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c0 - {0.533203f, 0.504883f, 0.548340f, 0.519531f, -0.1250f, -28.9375f, 30.0000f, 31, 30}, // 58c1 + {0.815430f, 0.527344f, 0.830566f, 0.541992f, -0.1250f, -28.9375f, 30.0000f, 31, 30}, // 58c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c6 - {0.400879f, 0.201172f, 0.416504f, 0.216309f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 58c7 + {0.613281f, 0.221191f, 0.628906f, 0.236328f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 58c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58c9 - {0.875000f, 0.048828f, 0.890625f, 0.064453f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 58ca + {0.439941f, 0.070801f, 0.455566f, 0.086426f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 58ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58cb - {0.582520f, 0.049316f, 0.598145f, 0.064941f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 58cc + {0.695801f, 0.070801f, 0.711426f, 0.086426f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 58cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d2 - {0.540527f, 0.427734f, 0.556152f, 0.442383f, -0.7500f, -28.2500f, 30.0000f, 32, 30}, // 58d3 + {0.746094f, 0.445801f, 0.761719f, 0.460449f, -0.7500f, -28.2500f, 30.0000f, 32, 30}, // 58d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58d6 @@ -3904,7 +4205,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58dd - {0.298828f, 0.049805f, 0.314453f, 0.065430f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 58de + {0.389160f, 0.072266f, 0.404785f, 0.087891f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 58de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58e1 @@ -3917,14 +4218,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ea - {0.542969f, 0.690430f, 0.556641f, 0.704102f, 1.0625f, -27.8750f, 30.0000f, 28, 28}, // 58eb + {0.984863f, 0.727539f, 0.998535f, 0.741211f, 1.0625f, -27.8750f, 30.0000f, 28, 28}, // 58eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ed - {0.286621f, 0.364258f, 0.301758f, 0.379395f, -0.8125f, -28.8750f, 30.0000f, 31, 31}, // 58ee + {0.031250f, 0.383301f, 0.046387f, 0.398438f, -0.8125f, -28.8750f, 30.0000f, 31, 31}, // 58ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58ef - {0.832031f, 0.364258f, 0.847168f, 0.379395f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 58f0 - {0.031250f, 0.504883f, 0.045898f, 0.520020f, 0.1875f, -29.4375f, 30.0000f, 30, 31}, // 58f1 - {0.354004f, 0.198242f, 0.369141f, 0.213867f, -0.1875f, -29.3750f, 30.0000f, 31, 32}, // 58f2 + {0.433105f, 0.383301f, 0.448242f, 0.398438f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 58f0 + {0.849121f, 0.527344f, 0.863770f, 0.542480f, 0.1875f, -29.4375f, 30.0000f, 30, 31}, // 58f1 + {0.079590f, 0.220703f, 0.094727f, 0.236328f, -0.1875f, -29.3750f, 30.0000f, 31, 32}, // 58f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 58f5 @@ -3945,49 +4246,49 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5904 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5905 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5906 - {0.847656f, 0.364258f, 0.862793f, 0.379395f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 5907 + {0.448730f, 0.383301f, 0.463867f, 0.398438f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 5907 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5908 - {0.416992f, 0.201660f, 0.432617f, 0.216797f, -0.2500f, -28.9375f, 30.0000f, 32, 31}, // 5909 + {0.129395f, 0.221680f, 0.145020f, 0.236816f, -0.2500f, -28.9375f, 30.0000f, 32, 31}, // 5909 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 590a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 590b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 590c - {0.110840f, 0.202148f, 0.126465f, 0.217285f, -0.3750f, -28.8750f, 30.0000f, 32, 31}, // 590d + {0.145508f, 0.221680f, 0.161133f, 0.236816f, -0.3750f, -28.8750f, 30.0000f, 32, 31}, // 590d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 590e - {0.320801f, 0.202637f, 0.336426f, 0.217773f, -0.4375f, -28.3750f, 30.0000f, 32, 31}, // 590f + {0.161621f, 0.221680f, 0.177246f, 0.236816f, -0.4375f, -28.3750f, 30.0000f, 32, 31}, // 590f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5910 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5911 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5912 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5913 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5914 - {0.859375f, 0.113281f, 0.872559f, 0.128906f, 0.8125f, -29.2500f, 30.0000f, 27, 32}, // 5915 - {0.314941f, 0.049805f, 0.330566f, 0.065430f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 5916 + {0.102539f, 0.687012f, 0.115723f, 0.702637f, 0.8125f, -29.2500f, 30.0000f, 27, 32}, // 5915 + {0.730469f, 0.072266f, 0.746094f, 0.087891f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 5916 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5917 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5918 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5919 - {0.138184f, 0.554688f, 0.152344f, 0.570313f, 0.6250f, -29.5000f, 30.0000f, 29, 32}, // 591a + {0.030273f, 0.580566f, 0.044434f, 0.596191f, 0.6250f, -29.5000f, 30.0000f, 29, 32}, // 591a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 591b - {0.000000f, 0.203613f, 0.015625f, 0.218750f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 591c + {0.177734f, 0.221680f, 0.193359f, 0.236816f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 591c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 591d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 591e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 591f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5920 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5921 - {0.016113f, 0.204102f, 0.031250f, 0.219727f, -0.3125f, -29.1875f, 30.0000f, 31, 32}, // 5922 + {0.193848f, 0.221680f, 0.208984f, 0.237305f, -0.3125f, -29.1875f, 30.0000f, 31, 32}, // 5922 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5923 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5924 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5925 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5926 - {0.709961f, 0.504883f, 0.724609f, 0.520020f, 0.5000f, -29.1250f, 30.0000f, 30, 31}, // 5927 + {0.323242f, 0.527832f, 0.337891f, 0.542969f, 0.5000f, -29.1250f, 30.0000f, 30, 31}, // 5927 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5928 - {0.523926f, 0.613281f, 0.539063f, 0.627441f, -0.1875f, -27.3750f, 30.0000f, 31, 29}, // 5929 - {0.680176f, 0.505371f, 0.694824f, 0.520508f, 0.4375f, -29.0625f, 30.0000f, 30, 31}, // 592a - {0.158691f, 0.365234f, 0.173828f, 0.380371f, 0.1875f, -29.0625f, 30.0000f, 31, 31}, // 592b + {0.273438f, 0.639160f, 0.288574f, 0.653320f, -0.1875f, -27.3750f, 30.0000f, 31, 29}, // 5929 + {0.373047f, 0.527832f, 0.387695f, 0.542969f, 0.4375f, -29.0625f, 30.0000f, 30, 31}, // 592a + {0.751953f, 0.383301f, 0.767090f, 0.398438f, 0.1875f, -29.0625f, 30.0000f, 31, 31}, // 592b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 592c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 592d - {0.031738f, 0.205078f, 0.047363f, 0.220215f, -0.4375f, -28.8125f, 30.0000f, 32, 31}, // 592e + {0.015625f, 0.222656f, 0.031250f, 0.237793f, -0.4375f, -28.8125f, 30.0000f, 32, 31}, // 592e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 592f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5930 - {0.169434f, 0.505859f, 0.184082f, 0.520996f, 0.5625f, -28.8750f, 30.0000f, 30, 31}, // 5931 + {0.982910f, 0.527832f, 0.997559f, 0.542969f, 0.5625f, -28.8750f, 30.0000f, 30, 31}, // 5931 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5932 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5933 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5934 @@ -3995,7 +4296,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5936 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5937 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5938 - {0.063477f, 0.205078f, 0.079102f, 0.220215f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 5939 + {0.000000f, 0.223145f, 0.015625f, 0.238281f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 5939 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 593a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 593b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 593c @@ -4009,20 +4310,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5944 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5945 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5946 - {0.336914f, 0.205078f, 0.352051f, 0.220703f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 5947 + {0.274414f, 0.223633f, 0.289551f, 0.239258f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 5947 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5948 - {0.331055f, 0.049805f, 0.346680f, 0.065430f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 5949 + {0.854980f, 0.072266f, 0.870605f, 0.087891f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 5949 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 594a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 594b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 594c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 594d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 594e - {0.504883f, 0.049805f, 0.520508f, 0.065430f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 594f + {0.871094f, 0.072754f, 0.886719f, 0.088379f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 594f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5950 - {0.520996f, 0.049805f, 0.536621f, 0.065430f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 5951 + {0.242188f, 0.074219f, 0.257813f, 0.089844f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 5951 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5952 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5953 - {0.475098f, 0.050293f, 0.490723f, 0.065918f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 5954 + {0.258301f, 0.074219f, 0.273926f, 0.089844f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 5954 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5955 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5956 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5957 @@ -4039,22 +4340,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5962 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5963 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5964 - {0.731934f, 0.050293f, 0.747559f, 0.065918f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5965 + {0.274414f, 0.074219f, 0.290039f, 0.089844f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5965 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5966 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5967 - {0.537109f, 0.051270f, 0.552734f, 0.066895f, -0.8750f, -29.5625f, 30.0000f, 32, 32}, // 5968 + {0.569824f, 0.074219f, 0.585449f, 0.089844f, -0.8750f, -29.5625f, 30.0000f, 32, 32}, // 5968 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5969 - {0.913574f, 0.000000f, 0.929688f, 0.015625f, -1.1250f, -29.3125f, 30.0000f, 33, 32}, // 596a + {0.226074f, 0.028809f, 0.242188f, 0.044434f, -1.1250f, -29.3125f, 30.0000f, 33, 32}, // 596a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 596b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 596c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 596d - {0.233887f, 0.051758f, 0.249512f, 0.067383f, -0.5000f, -29.5000f, 30.0000f, 32, 32}, // 596e + {0.585938f, 0.074219f, 0.601563f, 0.089844f, -0.5000f, -29.5000f, 30.0000f, 32, 32}, // 596e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 596f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5970 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5971 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5972 - {0.743652f, 0.613281f, 0.757813f, 0.628418f, 0.5625f, -29.1250f, 30.0000f, 29, 31}, // 5973 - {0.174316f, 0.365234f, 0.189453f, 0.380371f, -0.1250f, -28.5625f, 30.0000f, 31, 31}, // 5974 + {0.289063f, 0.639160f, 0.303223f, 0.654297f, 0.5625f, -29.1250f, 30.0000f, 29, 31}, // 5973 + {0.464355f, 0.383789f, 0.479492f, 0.398926f, -0.1250f, -28.5625f, 30.0000f, 31, 31}, // 5974 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5975 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5976 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5977 @@ -4063,20 +4364,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 597a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 597b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 597c - {0.047852f, 0.205566f, 0.063477f, 0.220703f, -0.5000f, -28.5625f, 30.0000f, 32, 31}, // 597d + {0.756348f, 0.223633f, 0.771973f, 0.238770f, -0.5000f, -28.5625f, 30.0000f, 32, 31}, // 597d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 597e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 597f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5980 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5981 - {0.664063f, 0.613770f, 0.678223f, 0.628906f, 0.1250f, -28.5000f, 30.0000f, 29, 31}, // 5982 - {0.079590f, 0.205566f, 0.095215f, 0.220703f, -1.1250f, -29.1875f, 30.0000f, 32, 31}, // 5983 - {0.095703f, 0.207520f, 0.110840f, 0.223145f, -0.3750f, -29.1250f, 30.0000f, 31, 32}, // 5984 + {0.610840f, 0.639160f, 0.625000f, 0.654297f, 0.1250f, -28.5000f, 30.0000f, 29, 31}, // 5982 + {0.772461f, 0.223633f, 0.788086f, 0.238770f, -1.1250f, -29.1875f, 30.0000f, 32, 31}, // 5983 + {0.255859f, 0.224121f, 0.270996f, 0.239746f, -0.3750f, -29.1250f, 30.0000f, 31, 32}, // 5984 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5985 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5986 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5987 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5988 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5989 - {0.179199f, 0.207520f, 0.194336f, 0.223145f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 598a + {0.290039f, 0.224121f, 0.305176f, 0.239746f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 598a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 598b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 598c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 598d @@ -4091,7 +4392,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5996 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5997 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5998 - {0.369629f, 0.207520f, 0.384766f, 0.223145f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 5999 + {0.305664f, 0.224121f, 0.320801f, 0.239746f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 5999 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 599a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 599b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 599c @@ -4103,10 +4404,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a4 - {0.062988f, 0.425293f, 0.077637f, 0.440918f, 0.0000f, -29.0000f, 30.0000f, 30, 32}, // 59a5 + {0.457031f, 0.446289f, 0.471680f, 0.461914f, 0.0000f, -29.0000f, 30.0000f, 30, 32}, // 59a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a7 - {0.126953f, 0.208008f, 0.142090f, 0.223633f, -0.3750f, -28.8750f, 30.0000f, 31, 32}, // 59a8 + {0.321289f, 0.224121f, 0.336426f, 0.239746f, -0.3750f, -28.8750f, 30.0000f, 31, 32}, // 59a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ab @@ -4123,9 +4424,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59b8 - {0.930176f, 0.000000f, 0.946289f, 0.015625f, -1.1250f, -29.0000f, 30.0000f, 33, 32}, // 59b9 + {0.826172f, 0.030762f, 0.842285f, 0.046387f, -1.1250f, -29.0000f, 30.0000f, 33, 32}, // 59b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ba - {0.032227f, 0.425781f, 0.046875f, 0.441406f, 0.3750f, -29.1875f, 30.0000f, 30, 32}, // 59bb + {0.284180f, 0.446777f, 0.298828f, 0.462402f, 0.3750f, -29.1875f, 30.0000f, 30, 32}, // 59bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59be @@ -4139,9 +4440,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59c8 - {0.250000f, 0.051758f, 0.265625f, 0.067383f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 59c9 + {0.711914f, 0.074707f, 0.727539f, 0.090332f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 59c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ca - {0.194824f, 0.208008f, 0.209961f, 0.223633f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 59cb + {0.031738f, 0.224609f, 0.046875f, 0.240234f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 59cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ce @@ -4149,8 +4450,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d2 - {0.655273f, 0.208008f, 0.670898f, 0.223145f, -0.5000f, -28.8125f, 30.0000f, 32, 31}, // 59d3 - {0.844727f, 0.426758f, 0.859375f, 0.442383f, -0.3125f, -29.1250f, 30.0000f, 30, 32}, // 59d4 + {0.466797f, 0.225586f, 0.482422f, 0.240723f, -0.5000f, -28.8125f, 30.0000f, 32, 31}, // 59d3 + {0.813477f, 0.446777f, 0.828125f, 0.462402f, -0.3125f, -29.1250f, 30.0000f, 30, 32}, // 59d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59d7 @@ -4173,7 +4474,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ea - {0.266113f, 0.051758f, 0.281738f, 0.067383f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 59eb + {0.746582f, 0.074707f, 0.762207f, 0.090332f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 59eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59ee @@ -4189,13 +4490,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59fa - {0.548828f, 0.505859f, 0.563477f, 0.520996f, -0.4375f, -28.9375f, 30.0000f, 30, 31}, // 59fb + {0.676270f, 0.528320f, 0.690918f, 0.543457f, -0.4375f, -28.9375f, 30.0000f, 30, 31}, // 59fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 59fe - {0.826660f, 0.208008f, 0.841797f, 0.223633f, -0.2500f, -29.3125f, 30.0000f, 31, 32}, // 59ff + {0.482910f, 0.225586f, 0.498047f, 0.241211f, -0.2500f, -29.3125f, 30.0000f, 31, 32}, // 59ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a00 - {0.282227f, 0.051758f, 0.297852f, 0.067383f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 5a01 + {0.762695f, 0.074707f, 0.778320f, 0.090332f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 5a01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a04 @@ -4218,7 +4519,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a17 - {0.390137f, 0.053223f, 0.405762f, 0.068848f, -0.1875f, -28.9375f, 30.0000f, 32, 32}, // 5a18 + {0.625000f, 0.075195f, 0.640625f, 0.090820f, -0.1875f, -28.9375f, 30.0000f, 32, 32}, // 5a18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a1b @@ -4226,7 +4527,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a1f - {0.142578f, 0.208496f, 0.158203f, 0.223633f, -0.0625f, -28.9375f, 30.0000f, 32, 31}, // 5a20 + {0.498535f, 0.225586f, 0.514160f, 0.240723f, -0.0625f, -28.9375f, 30.0000f, 32, 31}, // 5a20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a23 @@ -4241,7 +4542,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a2e - {0.158691f, 0.208496f, 0.173828f, 0.224121f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 5a2f + {0.788574f, 0.225586f, 0.803711f, 0.241211f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 5a2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a32 @@ -4264,7 +4565,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a45 - {0.530273f, 0.208496f, 0.545410f, 0.224121f, -0.0625f, -29.1250f, 30.0000f, 31, 32}, // 5a46 + {0.336914f, 0.226074f, 0.352051f, 0.241699f, -0.0625f, -29.1250f, 30.0000f, 31, 32}, // 5a46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a49 @@ -4284,7 +4585,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a59 - {0.440918f, 0.056152f, 0.456543f, 0.071777f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 5a5a + {0.641113f, 0.075195f, 0.656738f, 0.090820f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 5a5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a5d @@ -4296,7 +4597,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a65 - {0.457031f, 0.056641f, 0.472656f, 0.072266f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5a66 + {0.048340f, 0.075684f, 0.063965f, 0.091309f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5a66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a69 @@ -4321,7 +4622,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a7e - {0.141113f, 0.058105f, 0.156738f, 0.073730f, -0.1250f, -29.0625f, 30.0000f, 32, 32}, // 5a7f + {0.064453f, 0.075684f, 0.080078f, 0.091309f, -0.1250f, -29.0625f, 30.0000f, 32, 32}, // 5a7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a82 @@ -4340,7 +4641,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a91 - {0.157227f, 0.058105f, 0.172852f, 0.073730f, -0.2500f, -29.1250f, 30.0000f, 32, 32}, // 5a92 + {0.080566f, 0.075684f, 0.096191f, 0.091309f, -0.2500f, -29.1250f, 30.0000f, 32, 32}, // 5a92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5a95 @@ -4387,7 +4688,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5abe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5abf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ac0 - {0.347168f, 0.058594f, 0.362793f, 0.074219f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 5ac1 + {0.657227f, 0.076172f, 0.672852f, 0.091797f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 5ac1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ac2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ac3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ac4 @@ -4398,7 +4699,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ac9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5aca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5acb - {0.363281f, 0.058594f, 0.378906f, 0.074219f, -0.5000f, -29.5625f, 30.0000f, 32, 32}, // 5acc + {0.673340f, 0.076172f, 0.688965f, 0.091797f, -0.5000f, -29.5625f, 30.0000f, 32, 32}, // 5acc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5acd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ace {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5acf @@ -4419,7 +4720,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ade {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5adf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ae0 - {0.000000f, 0.059570f, 0.015625f, 0.075195f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 5ae1 + {0.160156f, 0.077148f, 0.175781f, 0.092773f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 5ae1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ae2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ae3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ae4 @@ -4484,7 +4785,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b21 - {0.016113f, 0.059570f, 0.031738f, 0.075195f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5b22 + {0.199707f, 0.077148f, 0.215332f, 0.092773f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5b22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b25 @@ -4530,34 +4831,34 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b4f - {0.502930f, 0.645996f, 0.517090f, 0.660645f, 0.9375f, -27.6250f, 30.0000f, 29, 30}, // 5b50 + {0.044434f, 0.673828f, 0.058594f, 0.688477f, 0.9375f, -27.6250f, 30.0000f, 29, 30}, // 5b50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b53 - {0.561035f, 0.365234f, 0.576172f, 0.380371f, 0.0000f, -28.8125f, 30.0000f, 31, 31}, // 5b54 + {0.285156f, 0.384277f, 0.300293f, 0.399414f, 0.0000f, -28.8125f, 30.0000f, 31, 31}, // 5b54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b56 - {0.694824f, 0.613770f, 0.708984f, 0.628906f, 0.8125f, -29.0000f, 30.0000f, 29, 31}, // 5b57 - {0.545898f, 0.208496f, 0.561035f, 0.224121f, -0.6250f, -29.1875f, 30.0000f, 31, 32}, // 5b58 + {0.758789f, 0.639160f, 0.772949f, 0.654297f, 0.8125f, -29.0000f, 30.0000f, 29, 31}, // 5b57 + {0.856934f, 0.226563f, 0.872070f, 0.242188f, -0.6250f, -29.1875f, 30.0000f, 31, 32}, // 5b58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b5c - {0.079102f, 0.365723f, 0.094238f, 0.380859f, -0.6250f, -29.0625f, 30.0000f, 31, 31}, // 5b5d + {0.816406f, 0.384277f, 0.831543f, 0.399414f, -0.6250f, -29.0625f, 30.0000f, 31, 31}, // 5b5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b62 - {0.032227f, 0.059570f, 0.047852f, 0.075195f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 5b63 - {0.048340f, 0.061035f, 0.063965f, 0.076660f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5b64 + {0.215820f, 0.077148f, 0.231445f, 0.092773f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 5b63 + {0.176270f, 0.077637f, 0.191895f, 0.093262f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5b64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b65 - {0.563965f, 0.505859f, 0.578613f, 0.520996f, 0.2500f, -28.8125f, 30.0000f, 30, 31}, // 5b66 + {0.592285f, 0.528809f, 0.606934f, 0.543945f, 0.2500f, -28.8125f, 30.0000f, 30, 31}, // 5b66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b6a - {0.561523f, 0.208496f, 0.577148f, 0.223633f, -0.6875f, -28.4375f, 30.0000f, 32, 31}, // 5b6b + {0.368652f, 0.228027f, 0.384277f, 0.243164f, -0.6875f, -28.4375f, 30.0000f, 32, 31}, // 5b6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b6e @@ -4583,14 +4884,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b84 - {0.319824f, 0.365723f, 0.334961f, 0.380859f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 5b85 + {0.300781f, 0.384766f, 0.315918f, 0.399902f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 5b85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b86 - {0.623535f, 0.208496f, 0.638672f, 0.224121f, -0.2500f, -29.2500f, 30.0000f, 31, 32}, // 5b87 - {0.755859f, 0.505859f, 0.770508f, 0.520996f, 0.3125f, -28.7500f, 30.0000f, 30, 31}, // 5b88 - {0.483887f, 0.506348f, 0.498535f, 0.521484f, 0.2500f, -28.5625f, 30.0000f, 30, 31}, // 5b89 + {0.417969f, 0.228027f, 0.433105f, 0.243652f, -0.2500f, -29.2500f, 30.0000f, 31, 32}, // 5b87 + {0.864258f, 0.528809f, 0.878906f, 0.543945f, 0.3125f, -28.7500f, 30.0000f, 30, 31}, // 5b88 + {0.879395f, 0.529297f, 0.894043f, 0.544434f, 0.2500f, -28.5625f, 30.0000f, 30, 31}, // 5b89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b8b - {0.691406f, 0.208496f, 0.706543f, 0.224121f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 5b8c + {0.547852f, 0.228027f, 0.562988f, 0.243652f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 5b8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b8f @@ -4601,20 +4902,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b96 - {0.592773f, 0.365723f, 0.607910f, 0.380859f, 0.1250f, -28.6875f, 30.0000f, 31, 31}, // 5b97 - {0.609863f, 0.208984f, 0.623535f, 0.224609f, 1.1250f, -29.1875f, 30.0000f, 28, 32}, // 5b98 - {0.423340f, 0.648926f, 0.437012f, 0.664063f, 1.1250f, -28.5000f, 30.0000f, 28, 31}, // 5b99 - {0.880859f, 0.208496f, 0.896484f, 0.223633f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 5b9a + {0.933594f, 0.384766f, 0.948730f, 0.399902f, 0.1250f, -28.6875f, 30.0000f, 31, 31}, // 5b97 + {0.303711f, 0.650879f, 0.317383f, 0.666504f, 1.1250f, -29.1875f, 30.0000f, 28, 32}, // 5b98 + {0.435547f, 0.683594f, 0.449219f, 0.698730f, 1.1250f, -28.5000f, 30.0000f, 28, 31}, // 5b99 + {0.891602f, 0.228027f, 0.907227f, 0.243164f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 5b9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5b9b - {0.579102f, 0.506348f, 0.594238f, 0.520996f, -0.1875f, -28.9375f, 30.0000f, 31, 30}, // 5b9c - {0.304688f, 0.584961f, 0.319336f, 0.599609f, 0.3750f, -28.8125f, 30.0000f, 30, 30}, // 5b9d - {0.642090f, 0.506348f, 0.656738f, 0.521484f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 5b9e - {0.896973f, 0.208496f, 0.912598f, 0.223633f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 5b9f + {0.338379f, 0.530762f, 0.353516f, 0.545410f, -0.1875f, -28.9375f, 30.0000f, 31, 30}, // 5b9c + {0.074707f, 0.611816f, 0.089355f, 0.626465f, 0.3750f, -28.8125f, 30.0000f, 30, 30}, // 5b9d + {0.091797f, 0.531250f, 0.106445f, 0.546387f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 5b9e + {0.433594f, 0.228516f, 0.449219f, 0.243652f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 5b9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ba0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ba1 - {0.577637f, 0.208984f, 0.593262f, 0.224121f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 5ba2 - {0.414063f, 0.584961f, 0.428711f, 0.599609f, 0.1875f, -28.7500f, 30.0000f, 30, 30}, // 5ba3 - {0.533203f, 0.645996f, 0.547363f, 0.660645f, 0.8125f, -28.8125f, 30.0000f, 29, 30}, // 5ba4 + {0.449707f, 0.228516f, 0.465332f, 0.243652f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 5ba2 + {0.119629f, 0.611816f, 0.134277f, 0.626465f, 0.1875f, -28.7500f, 30.0000f, 30, 30}, // 5ba3 + {0.467285f, 0.673828f, 0.481445f, 0.688477f, 0.8125f, -28.8125f, 30.0000f, 29, 30}, // 5ba4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ba5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ba6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ba7 @@ -4624,43 +4925,43 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bad - {0.166992f, 0.614258f, 0.181152f, 0.629395f, 0.9375f, -28.8750f, 30.0000f, 29, 31}, // 5bae + {0.089844f, 0.640137f, 0.104004f, 0.655273f, 0.9375f, -28.8750f, 30.0000f, 29, 31}, // 5bae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5baf - {0.807129f, 0.506836f, 0.821777f, 0.521973f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 5bb0 + {0.106934f, 0.531250f, 0.121582f, 0.546387f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 5bb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bb2 - {0.172363f, 0.427734f, 0.187012f, 0.443359f, 0.5000f, -29.0625f, 30.0000f, 30, 32}, // 5bb3 - {0.078125f, 0.428223f, 0.092773f, 0.443848f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // 5bb4 - {0.985840f, 0.444824f, 0.999512f, 0.460449f, 1.3125f, -29.1250f, 30.0000f, 28, 32}, // 5bb5 - {0.593750f, 0.208984f, 0.609375f, 0.224121f, -0.3750f, -28.7500f, 30.0000f, 32, 31}, // 5bb6 + {0.299316f, 0.447266f, 0.313965f, 0.462891f, 0.5000f, -29.0625f, 30.0000f, 30, 32}, // 5bb3 + {0.925293f, 0.447266f, 0.939941f, 0.462891f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // 5bb4 + {0.349121f, 0.651855f, 0.362793f, 0.667480f, 1.3125f, -29.1250f, 30.0000f, 28, 32}, // 5bb5 + {0.907715f, 0.228516f, 0.923340f, 0.243652f, -0.3750f, -28.7500f, 30.0000f, 32, 31}, // 5bb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bb8 - {0.064453f, 0.061035f, 0.080078f, 0.076660f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 5bb9 + {0.000000f, 0.078613f, 0.015625f, 0.094238f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 5bb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bbe - {0.314453f, 0.428223f, 0.329102f, 0.443848f, -0.7500f, -28.8750f, 30.0000f, 30, 32}, // 5bbf + {0.940430f, 0.447266f, 0.955078f, 0.462891f, -0.7500f, -28.8750f, 30.0000f, 30, 32}, // 5bbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc1 - {0.080566f, 0.061035f, 0.096191f, 0.076660f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 5bc2 + {0.016113f, 0.078613f, 0.031738f, 0.094238f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 5bc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc3 - {0.840820f, 0.506836f, 0.855469f, 0.521973f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 5bc4 + {0.292480f, 0.531738f, 0.307129f, 0.546875f, 0.3750f, -29.0000f, 30.0000f, 30, 31}, // 5bc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc5 - {0.639648f, 0.365723f, 0.654785f, 0.380859f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 5bc6 + {0.949219f, 0.384766f, 0.964355f, 0.399902f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 5bc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bc9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bcb - {0.937988f, 0.477539f, 0.951660f, 0.493164f, 1.1875f, -29.0625f, 30.0000f, 28, 32}, // 5bcc + {0.806641f, 0.651855f, 0.820313f, 0.667480f, 1.1875f, -29.0625f, 30.0000f, 28, 32}, // 5bcc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bcd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd1 - {0.096680f, 0.061035f, 0.112305f, 0.076660f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 5bd2 + {0.032227f, 0.078613f, 0.047852f, 0.094238f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 5bd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd5 @@ -4669,26 +4970,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bda - {0.112793f, 0.062988f, 0.128418f, 0.078613f, -0.3750f, -29.3125f, 30.0000f, 32, 32}, // 5bdb + {0.803223f, 0.079102f, 0.818848f, 0.094727f, -0.3750f, -29.3125f, 30.0000f, 32, 32}, // 5bdb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bdc - {0.173340f, 0.063477f, 0.188965f, 0.079102f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 5bdd + {0.819336f, 0.079102f, 0.834961f, 0.094727f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 5bdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bde - {0.707031f, 0.208984f, 0.722656f, 0.224121f, -0.4375f, -28.8125f, 30.0000f, 32, 31}, // 5bdf + {0.923828f, 0.228516f, 0.939453f, 0.243652f, -0.4375f, -28.8125f, 30.0000f, 32, 31}, // 5bdf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be0 - {0.946777f, 0.000000f, 0.962891f, 0.015625f, -1.0000f, -29.2500f, 30.0000f, 33, 32}, // 5be1 + {0.842773f, 0.030762f, 0.858887f, 0.046387f, -1.0000f, -29.2500f, 30.0000f, 33, 32}, // 5be1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be5 - {0.723145f, 0.208984f, 0.738281f, 0.224609f, -0.1875f, -29.5625f, 30.0000f, 31, 32}, // 5be6 - {0.585938f, 0.428223f, 0.600586f, 0.443848f, 0.3750f, -29.3750f, 30.0000f, 30, 32}, // 5be7 + {0.939941f, 0.228516f, 0.955078f, 0.244141f, -0.1875f, -29.5625f, 30.0000f, 31, 32}, // 5be6 + {0.955566f, 0.447266f, 0.970215f, 0.462891f, 0.3750f, -29.3750f, 30.0000f, 30, 32}, // 5be7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5be8 - {0.206055f, 0.063477f, 0.221680f, 0.079102f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 5be9 + {0.307129f, 0.079590f, 0.322754f, 0.095215f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 5be9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bea - {0.466797f, 0.554688f, 0.480957f, 0.570313f, 0.4375f, -29.0625f, 30.0000f, 29, 32}, // 5beb + {0.153320f, 0.580566f, 0.167480f, 0.596191f, 0.4375f, -29.0625f, 30.0000f, 29, 32}, // 5beb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bed - {0.406250f, 0.063477f, 0.421875f, 0.079102f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5bee + {0.323242f, 0.079590f, 0.338867f, 0.095215f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5bee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bf0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bf1 @@ -4698,32 +4999,32 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bf7 - {0.474609f, 0.614258f, 0.488770f, 0.629395f, 0.8750f, -28.8750f, 30.0000f, 29, 31}, // 5bf8 - {0.687988f, 0.365723f, 0.703125f, 0.380859f, -1.3125f, -28.9375f, 30.0000f, 31, 31}, // 5bf9 - {0.904297f, 0.506836f, 0.918945f, 0.521973f, 0.3125f, -29.0625f, 30.0000f, 30, 31}, // 5bfa + {0.104492f, 0.640137f, 0.118652f, 0.655273f, 0.8750f, -28.8750f, 30.0000f, 29, 31}, // 5bf8 + {0.964844f, 0.384766f, 0.979980f, 0.399902f, -1.3125f, -28.9375f, 30.0000f, 31, 31}, // 5bf9 + {0.307617f, 0.531738f, 0.322266f, 0.546875f, 0.3125f, -29.0625f, 30.0000f, 30, 31}, // 5bfa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bfb - {0.510742f, 0.584961f, 0.525391f, 0.599609f, -0.5000f, -27.6250f, 30.0000f, 30, 30}, // 5bfc + {0.505371f, 0.611816f, 0.520020f, 0.626465f, -0.5000f, -27.6250f, 30.0000f, 30, 30}, // 5bfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5bfd - {0.738770f, 0.208984f, 0.754395f, 0.224121f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 5bfe - {0.720703f, 0.365723f, 0.735840f, 0.380859f, -0.2500f, -29.1250f, 30.0000f, 31, 31}, // 5bff + {0.955566f, 0.228516f, 0.971191f, 0.243652f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 5bfe + {0.980469f, 0.384766f, 0.995605f, 0.399902f, -0.2500f, -29.1250f, 30.0000f, 31, 31}, // 5bff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c00 - {0.736328f, 0.365723f, 0.751465f, 0.380859f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 5c01 - {0.094727f, 0.366211f, 0.109863f, 0.381348f, -0.1875f, -28.7500f, 30.0000f, 31, 31}, // 5c02 + {0.849121f, 0.385254f, 0.864258f, 0.400391f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 5c01 + {0.334473f, 0.385742f, 0.349609f, 0.400879f, -0.1875f, -28.7500f, 30.0000f, 31, 31}, // 5c02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c03 - {0.754883f, 0.208984f, 0.770020f, 0.224609f, -0.5625f, -29.3750f, 30.0000f, 31, 32}, // 5c04 + {0.971680f, 0.228516f, 0.986816f, 0.244141f, -0.5625f, -29.3750f, 30.0000f, 31, 32}, // 5c04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c05 - {0.422363f, 0.063477f, 0.437988f, 0.079102f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5c06 - {0.715332f, 0.063477f, 0.730957f, 0.079102f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5c07 + {0.339355f, 0.079590f, 0.354980f, 0.095215f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 5c06 + {0.355469f, 0.079590f, 0.371094f, 0.095215f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5c07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c08 - {0.770508f, 0.208984f, 0.786133f, 0.224121f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 5c09 - {0.632813f, 0.428223f, 0.647461f, 0.443848f, 0.0625f, -29.5625f, 30.0000f, 30, 32}, // 5c0a - {0.311035f, 0.507324f, 0.325684f, 0.522461f, 0.1875f, -28.3750f, 30.0000f, 30, 31}, // 5c0b + {0.836426f, 0.229004f, 0.852051f, 0.244141f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 5c09 + {0.970703f, 0.447266f, 0.985352f, 0.462891f, 0.0625f, -29.5625f, 30.0000f, 30, 32}, // 5c0a + {0.354004f, 0.531738f, 0.368652f, 0.546875f, 0.1875f, -28.3750f, 30.0000f, 30, 31}, // 5c0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c0c - {0.786621f, 0.208984f, 0.802246f, 0.224121f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 5c0d - {0.913086f, 0.208984f, 0.928223f, 0.224609f, -0.3125f, -29.4375f, 30.0000f, 31, 32}, // 5c0e - {0.777832f, 0.584961f, 0.792480f, 0.599609f, 0.1250f, -28.5625f, 30.0000f, 30, 30}, // 5c0f + {0.872559f, 0.229004f, 0.888184f, 0.244141f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 5c0d + {0.110352f, 0.229492f, 0.125488f, 0.245117f, -0.3125f, -29.4375f, 30.0000f, 31, 32}, // 5c0e + {0.550293f, 0.611816f, 0.564941f, 0.626465f, 0.1250f, -28.5625f, 30.0000f, 30, 30}, // 5c0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c10 - {0.544434f, 0.366211f, 0.559570f, 0.381348f, -0.4375f, -28.5625f, 30.0000f, 31, 31}, // 5c11 + {0.398438f, 0.385742f, 0.413574f, 0.400879f, -0.4375f, -28.5625f, 30.0000f, 31, 31}, // 5c11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c14 @@ -4732,7 +5033,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c19 - {0.708008f, 0.647461f, 0.721191f, 0.663086f, 1.2500f, -29.1250f, 30.0000f, 27, 32}, // 5c1a + {0.725586f, 0.687012f, 0.738770f, 0.702637f, 1.2500f, -29.1250f, 30.0000f, 27, 32}, // 5c1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c1d @@ -4755,7 +5056,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c30 - {0.671387f, 0.366211f, 0.686523f, 0.381348f, -0.3125f, -29.0000f, 30.0000f, 31, 31}, // 5c31 + {0.414063f, 0.385742f, 0.429199f, 0.400879f, -0.3125f, -29.0000f, 30.0000f, 31, 31}, // 5c31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c34 @@ -4764,34 +5065,34 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c39 - {0.826172f, 0.584961f, 0.840820f, 0.599609f, 0.0625f, -27.0000f, 30.0000f, 30, 30}, // 5c3a + {0.182129f, 0.612305f, 0.196777f, 0.626953f, 0.0625f, -27.0000f, 30.0000f, 30, 30}, // 5c3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c3b - {0.421875f, 0.507324f, 0.437012f, 0.521973f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 5c3c - {0.686035f, 0.428223f, 0.701660f, 0.442871f, -0.8125f, -27.6875f, 30.0000f, 32, 30}, // 5c3d - {0.610840f, 0.507324f, 0.625977f, 0.521973f, -0.3125f, -27.5625f, 30.0000f, 31, 30}, // 5c3e - {0.657227f, 0.507813f, 0.672363f, 0.522461f, -0.4375f, -27.3750f, 30.0000f, 31, 30}, // 5c3f - {0.547852f, 0.645996f, 0.562012f, 0.660645f, 0.0000f, -27.5625f, 30.0000f, 29, 30}, // 5c40 + {0.625977f, 0.531738f, 0.641113f, 0.546387f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 5c3c + {0.506836f, 0.447754f, 0.522461f, 0.462402f, -0.8125f, -27.6875f, 30.0000f, 32, 30}, // 5c3d + {0.759277f, 0.531738f, 0.774414f, 0.546387f, -0.3125f, -27.5625f, 30.0000f, 31, 30}, // 5c3e + {0.774902f, 0.531738f, 0.790039f, 0.546387f, -0.4375f, -27.3750f, 30.0000f, 31, 30}, // 5c3f + {0.508789f, 0.673828f, 0.522949f, 0.688477f, 0.0000f, -27.5625f, 30.0000f, 29, 30}, // 5c40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c44 - {0.076660f, 0.508301f, 0.091797f, 0.522949f, -0.3125f, -27.5000f, 30.0000f, 31, 30}, // 5c45 + {0.661133f, 0.533203f, 0.676270f, 0.547852f, -0.3125f, -27.5000f, 30.0000f, 31, 30}, // 5c45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c47 - {0.398926f, 0.585449f, 0.413574f, 0.600098f, -0.5625f, -27.8125f, 30.0000f, 30, 30}, // 5c48 + {0.029297f, 0.612793f, 0.043945f, 0.627441f, -0.5625f, -27.8125f, 30.0000f, 30, 30}, // 5c48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c49 - {0.562500f, 0.645996f, 0.576660f, 0.660645f, -1.3750f, -27.7500f, 30.0000f, 29, 30}, // 5c4a - {0.801270f, 0.366211f, 0.816406f, 0.381348f, -0.4375f, -27.8750f, 30.0000f, 31, 31}, // 5c4b + {0.543457f, 0.673828f, 0.557617f, 0.688477f, -1.3750f, -27.7500f, 30.0000f, 29, 30}, // 5c4a + {0.523438f, 0.385742f, 0.538574f, 0.400879f, -0.4375f, -27.8750f, 30.0000f, 31, 31}, // 5c4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c4e - {0.184570f, 0.508301f, 0.199707f, 0.522949f, -0.4375f, -27.5625f, 30.0000f, 31, 30}, // 5c4f + {0.199219f, 0.533691f, 0.214355f, 0.548340f, -0.4375f, -27.5625f, 30.0000f, 31, 30}, // 5c4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c54 - {0.389648f, 0.508301f, 0.404785f, 0.522949f, -0.6250f, -27.3750f, 30.0000f, 31, 30}, // 5c55 + {0.514160f, 0.533691f, 0.529297f, 0.548340f, -0.6250f, -27.3750f, 30.0000f, 31, 30}, // 5c55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c58 @@ -4800,14 +5101,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c5d - {0.730957f, 0.585449f, 0.745605f, 0.600098f, -1.1250f, -27.3125f, 30.0000f, 30, 30}, // 5c5e + {0.150391f, 0.612793f, 0.165039f, 0.627441f, -1.1250f, -27.3125f, 30.0000f, 30, 30}, // 5c5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c63 - {0.468750f, 0.508301f, 0.483398f, 0.523438f, -0.5000f, -28.2500f, 30.0000f, 30, 31}, // 5c64 - {0.717285f, 0.428223f, 0.732910f, 0.442871f, -1.1250f, -27.6250f, 30.0000f, 32, 30}, // 5c65 + {0.468750f, 0.533691f, 0.483398f, 0.548828f, -0.5000f, -28.2500f, 30.0000f, 30, 31}, // 5c64 + {0.844238f, 0.447754f, 0.859863f, 0.462402f, -1.1250f, -27.6250f, 30.0000f, 32, 30}, // 5c65 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c68 @@ -4817,9 +5118,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c6e - {0.863281f, 0.366211f, 0.878418f, 0.381348f, 0.3125f, -29.1250f, 30.0000f, 31, 31}, // 5c6f + {0.883789f, 0.385742f, 0.898926f, 0.400879f, 0.3125f, -29.1250f, 30.0000f, 31, 31}, // 5c6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c70 - {0.463379f, 0.707520f, 0.476074f, 0.721680f, 2.0625f, -27.1875f, 30.0000f, 26, 29}, // 5c71 + {0.454590f, 0.751465f, 0.467285f, 0.765625f, 2.0625f, -27.1875f, 30.0000f, 26, 29}, // 5c71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c74 @@ -4850,7 +5151,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c8f - {0.928711f, 0.208984f, 0.943848f, 0.224609f, 0.2500f, -29.1250f, 30.0000f, 31, 32}, // 5c90 + {0.095215f, 0.230469f, 0.110352f, 0.246094f, 0.2500f, -29.1250f, 30.0000f, 31, 32}, // 5c90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5c93 @@ -4875,22 +5176,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ca6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ca7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ca8 - {0.517578f, 0.508301f, 0.532227f, 0.523438f, 0.0625f, -28.6875f, 30.0000f, 30, 31}, // 5ca9 + {0.562012f, 0.533691f, 0.576660f, 0.548828f, 0.0625f, -28.6875f, 30.0000f, 30, 31}, // 5ca9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5caa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cab - {0.539551f, 0.614258f, 0.553711f, 0.629395f, 0.4375f, -28.5000f, 30.0000f, 29, 31}, // 5cac + {0.334473f, 0.640625f, 0.348633f, 0.655762f, 0.4375f, -28.5000f, 30.0000f, 29, 31}, // 5cac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5caf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb2 - {0.594727f, 0.508301f, 0.609375f, 0.523438f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 5cb3 + {0.015137f, 0.534180f, 0.029785f, 0.549316f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 5cb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb7 - {0.499023f, 0.209473f, 0.514160f, 0.225098f, -0.9375f, -28.8750f, 30.0000f, 31, 32}, // 5cb8 + {0.730469f, 0.230957f, 0.745605f, 0.246582f, -0.9375f, -28.8750f, 30.0000f, 31, 32}, // 5cb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cbb @@ -4930,8 +5231,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cdf - {0.626465f, 0.508301f, 0.641113f, 0.523438f, 0.3750f, -29.0625f, 30.0000f, 30, 31}, // 5ce0 - {0.127441f, 0.366699f, 0.142578f, 0.381836f, 0.2500f, -28.8125f, 30.0000f, 31, 31}, // 5ce1 + {0.030273f, 0.534180f, 0.044922f, 0.549316f, 0.3750f, -29.0625f, 30.0000f, 30, 31}, // 5ce0 + {0.916992f, 0.385742f, 0.932129f, 0.400879f, 0.2500f, -28.8125f, 30.0000f, 31, 31}, // 5ce1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ce2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ce3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ce4 @@ -4946,13 +5247,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ced {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cef - {0.802734f, 0.209473f, 0.817871f, 0.225098f, 0.3125f, -29.2500f, 30.0000f, 31, 32}, // 5cf0 + {0.384766f, 0.231445f, 0.399902f, 0.247070f, 0.3125f, -29.2500f, 30.0000f, 31, 32}, // 5cf0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf5 - {0.852051f, 0.618164f, 0.865723f, 0.633789f, 1.5000f, -29.3750f, 30.0000f, 28, 32}, // 5cf6 + {0.820801f, 0.651855f, 0.834473f, 0.667480f, 1.5000f, -29.3750f, 30.0000f, 28, 32}, // 5cf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5cf9 @@ -4969,14 +5270,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d06 - {0.842285f, 0.209473f, 0.857422f, 0.225098f, -0.1250f, -29.0625f, 30.0000f, 31, 32}, // 5d07 + {0.400391f, 0.231445f, 0.415527f, 0.247070f, -0.1250f, -29.0625f, 30.0000f, 31, 32}, // 5d07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d0d - {0.733398f, 0.428223f, 0.748047f, 0.443848f, 0.3125f, -28.9375f, 30.0000f, 30, 32}, // 5d0e + {0.331055f, 0.448242f, 0.345703f, 0.463867f, 0.3125f, -28.9375f, 30.0000f, 30, 32}, // 5d0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d11 @@ -5003,7 +5304,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d28 - {0.796387f, 0.428223f, 0.811035f, 0.443848f, -0.2500f, -29.0625f, 30.0000f, 30, 32}, // 5d29 + {0.393555f, 0.448730f, 0.408203f, 0.464355f, -0.2500f, -29.0625f, 30.0000f, 30, 32}, // 5d29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5d2c @@ -5183,28 +5484,28 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ddb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ddc - {0.554199f, 0.614258f, 0.568359f, 0.629395f, -0.2500f, -28.5000f, 30.0000f, 29, 31}, // 5ddd - {0.568848f, 0.614258f, 0.583008f, 0.629395f, -0.3750f, -28.7500f, 30.0000f, 29, 31}, // 5dde + {0.625488f, 0.640625f, 0.639648f, 0.655762f, -0.2500f, -28.5000f, 30.0000f, 29, 31}, // 5ddd + {0.743652f, 0.640625f, 0.757813f, 0.655762f, -0.3750f, -28.7500f, 30.0000f, 29, 31}, // 5dde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ddf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5de0 - {0.857910f, 0.209473f, 0.873535f, 0.224609f, -1.3750f, -28.5625f, 30.0000f, 32, 31}, // 5de1 + {0.629395f, 0.231934f, 0.645020f, 0.247070f, -1.3750f, -28.5625f, 30.0000f, 32, 31}, // 5de1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5de2 - {0.944336f, 0.209473f, 0.959961f, 0.224609f, -0.1875f, -29.1250f, 30.0000f, 32, 31}, // 5de3 + {0.674805f, 0.232422f, 0.690430f, 0.247559f, -0.1875f, -29.1250f, 30.0000f, 32, 31}, // 5de3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5de4 - {0.802734f, 0.537598f, 0.816895f, 0.549316f, 0.8750f, -24.8750f, 30.0000f, 29, 24}, // 5de5 - {0.725098f, 0.508301f, 0.740234f, 0.522949f, -0.3750f, -28.6250f, 30.0000f, 31, 30}, // 5de6 - {0.633789f, 0.614258f, 0.648926f, 0.628418f, -0.2500f, -27.1875f, 30.0000f, 31, 29}, // 5de7 - {0.233887f, 0.678711f, 0.247070f, 0.693359f, 3.0625f, -27.7500f, 30.0000f, 27, 30}, // 5de8 + {0.887207f, 0.072754f, 0.901367f, 0.084473f, 0.8750f, -24.8750f, 30.0000f, 29, 24}, // 5de5 + {0.045410f, 0.534180f, 0.060547f, 0.548828f, -0.3750f, -28.6250f, 30.0000f, 31, 30}, // 5de6 + {0.195801f, 0.641113f, 0.210938f, 0.655273f, -0.2500f, -27.1875f, 30.0000f, 31, 29}, // 5de7 + {0.608398f, 0.718750f, 0.621582f, 0.733398f, 3.0625f, -27.7500f, 30.0000f, 27, 30}, // 5de8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5de9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5deb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ded - {0.740723f, 0.508301f, 0.755859f, 0.522949f, -0.6250f, -29.2500f, 30.0000f, 31, 30}, // 5dee + {0.061035f, 0.534180f, 0.076172f, 0.548828f, -0.6250f, -29.2500f, 30.0000f, 31, 30}, // 5dee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5def {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df0 - {0.270020f, 0.706055f, 0.283691f, 0.719238f, 1.3750f, -26.9375f, 30.0000f, 28, 27}, // 5df1 - {0.557129f, 0.690430f, 0.570801f, 0.704102f, 2.1250f, -26.9375f, 30.0000f, 28, 28}, // 5df2 + {0.597168f, 0.749023f, 0.610840f, 0.762207f, 1.3750f, -26.9375f, 30.0000f, 28, 27}, // 5df1 + {0.791016f, 0.728027f, 0.804688f, 0.741699f, 2.1250f, -26.9375f, 30.0000f, 28, 28}, // 5df2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df5 @@ -5213,24 +5514,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5df9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dfa - {0.960449f, 0.209473f, 0.976074f, 0.224609f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 5dfb + {0.352539f, 0.233398f, 0.368164f, 0.248535f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 5dfb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5dff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e01 - {0.770996f, 0.508301f, 0.785645f, 0.523438f, 0.1250f, -28.8125f, 30.0000f, 30, 31}, // 5e02 - {0.093262f, 0.428711f, 0.107910f, 0.444336f, -0.2500f, -29.0625f, 30.0000f, 30, 32}, // 5e03 + {0.076660f, 0.534180f, 0.091309f, 0.549316f, 0.1250f, -28.8125f, 30.0000f, 30, 31}, // 5e02 + {0.408691f, 0.448730f, 0.423340f, 0.464355f, -0.2500f, -29.0625f, 30.0000f, 30, 32}, // 5e03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e05 - {0.523438f, 0.428711f, 0.538086f, 0.444336f, 0.8125f, -28.8750f, 30.0000f, 30, 32}, // 5e06 + {0.876465f, 0.448730f, 0.891113f, 0.464355f, 0.8125f, -28.8750f, 30.0000f, 30, 32}, // 5e06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e0b - {0.976563f, 0.209473f, 0.991699f, 0.225098f, -0.1250f, -29.3750f, 30.0000f, 31, 32}, // 5e0c + {0.804199f, 0.233398f, 0.819336f, 0.249023f, -0.1250f, -29.3750f, 30.0000f, 31, 32}, // 5e0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e0f @@ -5247,7 +5548,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e1c - {0.271973f, 0.619629f, 0.285645f, 0.635254f, 1.0625f, -29.0625f, 30.0000f, 28, 32}, // 5e1d + {0.654785f, 0.652344f, 0.668457f, 0.667969f, 1.0625f, -29.0625f, 30.0000f, 28, 32}, // 5e1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e20 @@ -5255,39 +5556,39 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e24 - {0.678711f, 0.619629f, 0.692383f, 0.635254f, 1.4375f, -29.5625f, 30.0000f, 28, 32}, // 5e25 + {0.834961f, 0.652344f, 0.848633f, 0.667969f, 1.4375f, -29.5625f, 30.0000f, 28, 32}, // 5e25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e26 - {0.786133f, 0.508301f, 0.800781f, 0.523438f, 0.6250f, -28.8125f, 30.0000f, 30, 31}, // 5e27 + {0.122070f, 0.534180f, 0.136719f, 0.549316f, 0.6250f, -28.8125f, 30.0000f, 30, 31}, // 5e27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e2a - {0.668945f, 0.428711f, 0.683594f, 0.444336f, 1.3125f, -29.3750f, 30.0000f, 30, 32}, // 5e2b + {0.909668f, 0.448730f, 0.924316f, 0.464355f, 1.3125f, -29.3750f, 30.0000f, 30, 32}, // 5e2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e2c - {0.508789f, 0.366699f, 0.523926f, 0.381836f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 5e2d - {0.524414f, 0.366699f, 0.539551f, 0.381836f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 5e2e - {0.934082f, 0.508301f, 0.948730f, 0.523438f, -0.0625f, -28.8750f, 30.0000f, 30, 31}, // 5e2f - {0.949219f, 0.508301f, 0.963867f, 0.523438f, 0.6250f, -28.2500f, 30.0000f, 30, 31}, // 5e30 + {0.382324f, 0.386230f, 0.397461f, 0.401367f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 5e2d + {0.864746f, 0.387207f, 0.879883f, 0.402344f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 5e2e + {0.184570f, 0.534180f, 0.199219f, 0.549316f, -0.0625f, -28.8750f, 30.0000f, 30, 31}, // 5e2f + {0.483887f, 0.534180f, 0.498535f, 0.549316f, 0.6250f, -28.2500f, 30.0000f, 30, 31}, // 5e30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e32 - {0.608398f, 0.366699f, 0.623535f, 0.381836f, 0.4375f, -28.8750f, 30.0000f, 31, 31}, // 5e33 + {0.832031f, 0.387695f, 0.847168f, 0.402832f, 0.4375f, -28.8750f, 30.0000f, 31, 31}, // 5e33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e37 - {0.498047f, 0.554688f, 0.512207f, 0.570313f, 0.8125f, -29.0625f, 30.0000f, 29, 32}, // 5e38 + {0.477051f, 0.580566f, 0.491211f, 0.596191f, 0.8125f, -29.0625f, 30.0000f, 29, 32}, // 5e38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e3c - {0.590820f, 0.554688f, 0.604980f, 0.570313f, 0.8125f, -28.8750f, 30.0000f, 29, 32}, // 5e3d + {0.526367f, 0.580566f, 0.540527f, 0.596191f, 0.8125f, -28.8750f, 30.0000f, 29, 32}, // 5e3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e3f - {0.288574f, 0.209961f, 0.303711f, 0.225586f, 0.3125f, -28.9375f, 30.0000f, 31, 32}, // 5e40 + {0.819824f, 0.233398f, 0.834961f, 0.249023f, 0.3125f, -28.9375f, 30.0000f, 31, 32}, // 5e40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e44 - {0.092285f, 0.508789f, 0.106934f, 0.523926f, 0.5625f, -28.8750f, 30.0000f, 30, 31}, // 5e45 + {0.529785f, 0.534180f, 0.544434f, 0.549316f, 0.5625f, -28.8750f, 30.0000f, 30, 31}, // 5e45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e48 @@ -5303,7 +5604,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e54 - {0.941406f, 0.366699f, 0.956543f, 0.381836f, -0.3125f, -29.0625f, 30.0000f, 31, 31}, // 5e55 + {0.096191f, 0.388184f, 0.111328f, 0.403320f, -0.3125f, -29.0625f, 30.0000f, 31, 31}, // 5e55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e58 @@ -5317,7 +5618,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e62 - {0.304199f, 0.209961f, 0.319336f, 0.225586f, 0.6250f, -29.1875f, 30.0000f, 31, 32}, // 5e63 + {0.514648f, 0.234375f, 0.529785f, 0.250000f, 0.6250f, -29.1875f, 30.0000f, 31, 32}, // 5e63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e65 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e66 @@ -5325,56 +5626,56 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e6a - {0.973145f, 0.366699f, 0.988281f, 0.381836f, -0.3750f, -29.0625f, 30.0000f, 31, 31}, // 5e6b + {0.899414f, 0.388184f, 0.914551f, 0.403320f, -0.3750f, -29.0625f, 30.0000f, 31, 31}, // 5e6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e71 - {0.635742f, 0.663086f, 0.649414f, 0.677734f, 1.0000f, -27.3750f, 30.0000f, 28, 30}, // 5e72 - {0.762207f, 0.585449f, 0.776855f, 0.600098f, 0.1250f, -27.6250f, 30.0000f, 30, 30}, // 5e73 - {0.622070f, 0.554688f, 0.636230f, 0.570313f, 0.5625f, -29.2500f, 30.0000f, 29, 32}, // 5e74 + {0.958984f, 0.699219f, 0.972656f, 0.713867f, 1.0000f, -27.3750f, 30.0000f, 28, 30}, // 5e72 + {0.471191f, 0.612793f, 0.485840f, 0.627441f, 0.1250f, -27.6250f, 30.0000f, 30, 30}, // 5e73 + {0.541016f, 0.580566f, 0.555176f, 0.596191f, 0.5625f, -29.2500f, 30.0000f, 29, 32}, // 5e74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e77 - {0.717773f, 0.554688f, 0.731934f, 0.570313f, 0.8125f, -29.0000f, 30.0000f, 29, 32}, // 5e78 - {0.189453f, 0.063965f, 0.205078f, 0.079590f, -0.1875f, -29.3750f, 30.0000f, 32, 32}, // 5e79 + {0.606934f, 0.580566f, 0.621094f, 0.596191f, 0.8125f, -29.0000f, 30.0000f, 29, 32}, // 5e78 + {0.371582f, 0.079590f, 0.387207f, 0.095215f, -0.1875f, -29.3750f, 30.0000f, 32, 32}, // 5e79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e7a - {0.089355f, 0.585938f, 0.104004f, 0.600586f, -0.4375f, -28.2500f, 30.0000f, 30, 30}, // 5e7b - {0.122559f, 0.508789f, 0.137207f, 0.523926f, -0.4375f, -28.8125f, 30.0000f, 30, 31}, // 5e7c - {0.456055f, 0.648926f, 0.469727f, 0.664063f, 1.4375f, -29.0000f, 30.0000f, 28, 31}, // 5e7d - {0.385254f, 0.209961f, 0.400391f, 0.225586f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 5e7e + {0.520508f, 0.612793f, 0.535156f, 0.627441f, -0.4375f, -28.2500f, 30.0000f, 30, 30}, // 5e7b + {0.607422f, 0.534180f, 0.622070f, 0.549316f, -0.4375f, -28.8125f, 30.0000f, 30, 31}, // 5e7c + {0.572754f, 0.683594f, 0.586426f, 0.698730f, 1.4375f, -29.0000f, 30.0000f, 28, 31}, // 5e7d + {0.530273f, 0.234375f, 0.545410f, 0.250000f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 5e7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e80 - {0.143066f, 0.367188f, 0.158203f, 0.382324f, -1.0000f, -28.8125f, 30.0000f, 31, 31}, // 5e81 + {0.350098f, 0.388672f, 0.365234f, 0.403809f, -1.0000f, -28.8125f, 30.0000f, 31, 31}, // 5e81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e82 - {0.415527f, 0.367188f, 0.430664f, 0.382324f, -0.6875f, -28.6875f, 30.0000f, 31, 31}, // 5e83 + {0.617676f, 0.389160f, 0.632813f, 0.404297f, -0.6875f, -28.6875f, 30.0000f, 31, 31}, // 5e83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e89 - {0.449219f, 0.209961f, 0.464844f, 0.225098f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 5e8a + {0.209473f, 0.234863f, 0.225098f, 0.250000f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 5e8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e8e - {0.514648f, 0.209961f, 0.529785f, 0.225586f, -0.6875f, -28.9375f, 30.0000f, 31, 32}, // 5e8f + {0.225586f, 0.234863f, 0.240723f, 0.250488f, -0.6875f, -28.9375f, 30.0000f, 31, 32}, // 5e8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e92 - {0.639160f, 0.209961f, 0.654297f, 0.225586f, -1.1875f, -29.2500f, 30.0000f, 31, 32}, // 5e93 - {0.576660f, 0.367188f, 0.591797f, 0.382324f, -0.6250f, -29.0625f, 30.0000f, 31, 31}, // 5e94 - {0.598633f, 0.064453f, 0.614258f, 0.080078f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5e95 + {0.563477f, 0.235352f, 0.578613f, 0.250977f, -1.1875f, -29.2500f, 30.0000f, 31, 32}, // 5e93 + {0.365723f, 0.389648f, 0.380859f, 0.404785f, -0.6250f, -29.0625f, 30.0000f, 31, 31}, // 5e94 + {0.290527f, 0.080078f, 0.306152f, 0.095703f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 5e95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e96 - {0.614746f, 0.064453f, 0.630371f, 0.080078f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 5e97 + {0.530273f, 0.081055f, 0.545898f, 0.096680f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 5e97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e9b - {0.258301f, 0.210449f, 0.273438f, 0.226074f, -0.8125f, -29.0000f, 30.0000f, 31, 32}, // 5e9c + {0.579102f, 0.235352f, 0.594238f, 0.250977f, -0.8125f, -29.0000f, 30.0000f, 31, 32}, // 5e9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5e9f @@ -5384,14 +5685,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ea3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ea4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ea5 - {0.465332f, 0.210449f, 0.480957f, 0.225586f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 5ea6 - {0.751953f, 0.367188f, 0.767090f, 0.382324f, -0.5625f, -28.6875f, 30.0000f, 31, 31}, // 5ea7 + {0.645508f, 0.235352f, 0.661133f, 0.250488f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 5ea6 + {0.703125f, 0.389648f, 0.718262f, 0.404785f, -0.5625f, -28.6875f, 30.0000f, 31, 31}, // 5ea7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ea8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ea9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eaa - {0.433105f, 0.210938f, 0.448242f, 0.226563f, -0.3750f, -28.8750f, 30.0000f, 31, 32}, // 5eab + {0.690918f, 0.235352f, 0.706055f, 0.250977f, -0.3750f, -28.8750f, 30.0000f, 31, 32}, // 5eab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eac - {0.630859f, 0.064453f, 0.646484f, 0.080078f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 5ead + {0.546387f, 0.081055f, 0.562012f, 0.096680f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 5ead {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eaf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eb0 @@ -5400,9 +5701,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eb5 - {0.671387f, 0.210938f, 0.687012f, 0.226074f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 5eb6 - {0.481445f, 0.211426f, 0.497070f, 0.226563f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 5eb7 - {0.646973f, 0.064453f, 0.662598f, 0.080078f, -0.5625f, -29.3750f, 30.0000f, 32, 32}, // 5eb8 + {0.706543f, 0.235352f, 0.722168f, 0.250488f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 5eb6 + {0.047363f, 0.236328f, 0.062988f, 0.251465f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 5eb7 + {0.835449f, 0.081055f, 0.851074f, 0.096680f, -0.5625f, -29.3750f, 30.0000f, 32, 32}, // 5eb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ebb @@ -5413,14 +5714,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec2 - {0.663086f, 0.064453f, 0.678711f, 0.080078f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5ec3 + {0.917480f, 0.082520f, 0.933105f, 0.098145f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 5ec3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ec8 - {0.679199f, 0.064453f, 0.694824f, 0.080078f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 5ec9 - {0.210449f, 0.211914f, 0.226074f, 0.227051f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5eca + {0.405273f, 0.083984f, 0.420898f, 0.099609f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 5ec9 + {0.063477f, 0.236816f, 0.079102f, 0.251953f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5eca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ecb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ecc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ecd @@ -5464,19 +5765,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ef3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ef4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ef5 - {0.242188f, 0.212402f, 0.257813f, 0.227539f, -1.0000f, -28.7500f, 30.0000f, 32, 31}, // 5ef6 - {0.226563f, 0.212891f, 0.242188f, 0.228027f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 5ef7 + {0.079590f, 0.236816f, 0.095215f, 0.251953f, -1.0000f, -28.7500f, 30.0000f, 32, 31}, // 5ef6 + {0.594727f, 0.236816f, 0.610352f, 0.251953f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 5ef7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ef8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ef9 - {0.352539f, 0.214355f, 0.368164f, 0.229492f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 5efa + {0.610840f, 0.236816f, 0.626465f, 0.251953f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 5efa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5efb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5efc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5efd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5efe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5eff - {0.137695f, 0.508789f, 0.152832f, 0.523438f, -0.9375f, -27.3750f, 30.0000f, 31, 30}, // 5f00 - {0.748047f, 0.064453f, 0.763672f, 0.080078f, -0.6250f, -29.5000f, 30.0000f, 32, 32}, // 5f01 - {0.215820f, 0.508789f, 0.230957f, 0.523438f, -0.3750f, -27.5625f, 30.0000f, 31, 30}, // 5f02 + {0.641602f, 0.534180f, 0.656738f, 0.548828f, -0.9375f, -27.3750f, 30.0000f, 31, 30}, // 5f00 + {0.456055f, 0.083984f, 0.471680f, 0.099609f, -0.6250f, -29.5000f, 30.0000f, 32, 32}, // 5f01 + {0.153809f, 0.534668f, 0.168945f, 0.549316f, -0.3750f, -27.5625f, 30.0000f, 31, 30}, // 5f02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f05 @@ -5484,18 +5785,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f09 - {0.400879f, 0.216797f, 0.416016f, 0.232422f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 5f0a + {0.125977f, 0.237305f, 0.141113f, 0.252930f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 5f0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f0e - {0.767578f, 0.367188f, 0.782715f, 0.382324f, 0.2500f, -29.0625f, 30.0000f, 31, 31}, // 5f0f - {0.911621f, 0.367188f, 0.926758f, 0.382324f, 0.2500f, -29.0625f, 30.0000f, 31, 31}, // 5f10 + {0.316406f, 0.390625f, 0.331543f, 0.405762f, 0.2500f, -29.0625f, 30.0000f, 31, 31}, // 5f0f + {0.652832f, 0.390625f, 0.667969f, 0.405762f, 0.2500f, -29.0625f, 30.0000f, 31, 31}, // 5f10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f12 - {0.872070f, 0.692871f, 0.884766f, 0.707520f, 2.2500f, -27.6875f, 30.0000f, 26, 30}, // 5f13 - {0.860840f, 0.663086f, 0.874512f, 0.677734f, 1.2500f, -27.3750f, 30.0000f, 28, 30}, // 5f14 - {0.000000f, 0.680664f, 0.012695f, 0.695801f, 2.1250f, -28.8125f, 30.0000f, 26, 31}, // 5f15 + {0.604492f, 0.733887f, 0.617188f, 0.748535f, 2.2500f, -27.6875f, 30.0000f, 26, 30}, // 5f13 + {0.312988f, 0.699707f, 0.326660f, 0.714355f, 1.2500f, -27.3750f, 30.0000f, 28, 30}, // 5f14 + {0.622070f, 0.720215f, 0.634766f, 0.735352f, 2.1250f, -28.8125f, 30.0000f, 26, 31}, // 5f15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f18 @@ -5505,15 +5806,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f1e - {0.140137f, 0.429199f, 0.154785f, 0.444824f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // 5f1f + {0.377930f, 0.449219f, 0.392578f, 0.464844f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // 5f1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f25 - {0.957031f, 0.367188f, 0.972168f, 0.382324f, 0.3750f, -28.5625f, 30.0000f, 31, 31}, // 5f26 - {0.416504f, 0.217285f, 0.431641f, 0.232910f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 5f27 + {0.785645f, 0.391602f, 0.800781f, 0.406738f, 0.3750f, -28.5625f, 30.0000f, 31, 31}, // 5f26 + {0.141602f, 0.237305f, 0.156738f, 0.252930f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 5f27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f2a @@ -5523,20 +5824,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f30 - {0.229004f, 0.585938f, 0.243652f, 0.600586f, -0.3750f, -27.6250f, 30.0000f, 30, 30}, // 5f31 + {0.535645f, 0.612793f, 0.550293f, 0.627441f, -0.3750f, -27.6250f, 30.0000f, 30, 30}, // 5f31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f34 - {0.231445f, 0.508789f, 0.246582f, 0.523438f, 0.0000f, -27.9375f, 30.0000f, 31, 30}, // 5f35 + {0.544922f, 0.534668f, 0.560059f, 0.549316f, 0.0000f, -27.9375f, 30.0000f, 31, 30}, // 5f35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f36 - {0.237793f, 0.367676f, 0.252930f, 0.382813f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 5f37 + {0.801270f, 0.391602f, 0.816406f, 0.406738f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 5f37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f39 - {0.326172f, 0.508789f, 0.341309f, 0.523438f, -0.1250f, -27.0000f, 30.0000f, 31, 30}, // 5f3a + {0.137207f, 0.535156f, 0.152344f, 0.549805f, -0.1250f, -27.0000f, 30.0000f, 31, 30}, // 5f3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f3d - {0.270508f, 0.367676f, 0.285645f, 0.382813f, 0.0000f, -29.0625f, 30.0000f, 31, 31}, // 5f3e + {0.506836f, 0.392090f, 0.521973f, 0.407227f, 0.0000f, -29.0625f, 30.0000f, 31, 31}, // 5f3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f41 @@ -5557,13 +5858,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f52 - {0.268555f, 0.666504f, 0.281738f, 0.681641f, 1.6875f, -28.9375f, 30.0000f, 27, 31}, // 5f53 + {0.521973f, 0.704590f, 0.535156f, 0.719727f, 1.6875f, -28.9375f, 30.0000f, 27, 31}, // 5f53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f54 - {0.405273f, 0.508789f, 0.420410f, 0.523438f, 0.1250f, -27.6875f, 30.0000f, 31, 30}, // 5f55 + {0.740234f, 0.535645f, 0.755371f, 0.550293f, 0.1250f, -27.6875f, 30.0000f, 31, 30}, // 5f55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f58 - {0.963379f, 0.000000f, 0.979492f, 0.015625f, -1.1250f, -29.2500f, 30.0000f, 33, 32}, // 5f59 + {0.301270f, 0.031250f, 0.317383f, 0.046875f, -1.1250f, -29.2500f, 30.0000f, 33, 32}, // 5f59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f5c @@ -5572,22 +5873,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f61 - {0.335449f, 0.367676f, 0.350586f, 0.382813f, -0.2500f, -28.8750f, 30.0000f, 31, 31}, // 5f62 + {0.633301f, 0.392090f, 0.648438f, 0.407227f, -0.2500f, -28.8750f, 30.0000f, 31, 31}, // 5f62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f65 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f68 - {0.111328f, 0.217773f, 0.126953f, 0.232910f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 5f69 + {0.157227f, 0.237305f, 0.172852f, 0.252441f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 5f69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f6a - {0.764160f, 0.064453f, 0.779785f, 0.080078f, -0.8125f, -29.3750f, 30.0000f, 32, 32}, // 5f6b + {0.472168f, 0.083984f, 0.487793f, 0.099609f, -0.8125f, -29.3750f, 30.0000f, 32, 32}, // 5f6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f6f - {0.780273f, 0.064453f, 0.795898f, 0.080078f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 5f70 - {0.319824f, 0.218262f, 0.335449f, 0.233398f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 5f71 + {0.488281f, 0.083984f, 0.503906f, 0.099609f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 5f70 + {0.173340f, 0.237305f, 0.188965f, 0.252441f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 5f71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f74 @@ -5595,37 +5896,37 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f78 - {0.796387f, 0.064453f, 0.812012f, 0.080078f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 5f79 + {0.504395f, 0.083984f, 0.520020f, 0.099609f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 5f79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f7b - {0.812500f, 0.064453f, 0.828125f, 0.080078f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 5f7c + {0.602051f, 0.083984f, 0.617676f, 0.099609f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 5f7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f7f - {0.351074f, 0.367676f, 0.366211f, 0.382813f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 5f80 - {0.828613f, 0.064453f, 0.844238f, 0.080078f, -1.0625f, -29.1250f, 30.0000f, 32, 32}, // 5f81 + {0.685059f, 0.392090f, 0.700195f, 0.407227f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 5f80 + {0.957520f, 0.083984f, 0.973145f, 0.099609f, -1.0625f, -29.1250f, 30.0000f, 32, 32}, // 5f81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f83 - {0.000000f, 0.219238f, 0.015625f, 0.234375f, -0.6875f, -29.0000f, 30.0000f, 32, 31}, // 5f84 - {0.844727f, 0.064453f, 0.860352f, 0.080078f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5f85 + {0.189453f, 0.237793f, 0.205078f, 0.252930f, -0.6875f, -29.0000f, 30.0000f, 32, 31}, // 5f84 + {0.973633f, 0.083984f, 0.989258f, 0.099609f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 5f85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f8a - {0.016113f, 0.220215f, 0.031738f, 0.235352f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 5f8b - {0.891113f, 0.064453f, 0.906738f, 0.080078f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 5f8c + {0.016113f, 0.238281f, 0.031738f, 0.253418f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 5f8b + {0.887207f, 0.084473f, 0.902832f, 0.100098f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 5f8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f8f - {0.907227f, 0.064453f, 0.922852f, 0.080078f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 5f90 - {0.923340f, 0.064453f, 0.938965f, 0.080078f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 5f91 - {0.939453f, 0.064453f, 0.955078f, 0.080078f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 5f92 - {0.955566f, 0.064453f, 0.971191f, 0.080078f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 5f93 + {0.933594f, 0.084961f, 0.949219f, 0.100586f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 5f90 + {0.096680f, 0.085938f, 0.112305f, 0.101563f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 5f91 + {0.112793f, 0.085938f, 0.128418f, 0.101563f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 5f92 + {0.128906f, 0.086426f, 0.144531f, 0.102051f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 5f93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f96 - {0.032227f, 0.220703f, 0.047363f, 0.236328f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 5f97 + {0.000000f, 0.238770f, 0.015137f, 0.254395f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 5f97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f9a @@ -5635,7 +5936,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5f9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa0 - {0.624023f, 0.367676f, 0.639160f, 0.382813f, -0.9375f, -29.1250f, 30.0000f, 31, 31}, // 5fa1 + {0.767578f, 0.392090f, 0.782715f, 0.407227f, -0.9375f, -29.1250f, 30.0000f, 31, 31}, // 5fa1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa4 @@ -5643,23 +5944,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fa8 - {0.971680f, 0.064453f, 0.987305f, 0.080078f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 5fa9 - {0.553223f, 0.064941f, 0.568848f, 0.080566f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5faa + {0.778809f, 0.086426f, 0.794434f, 0.102051f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 5fa9 + {0.421387f, 0.086914f, 0.437012f, 0.102539f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 5faa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fad - {0.695313f, 0.064941f, 0.710938f, 0.080566f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 5fae + {0.437500f, 0.086914f, 0.453125f, 0.102539f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 5fae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5faf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb2 - {0.860840f, 0.064941f, 0.876465f, 0.080566f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 5fb3 - {0.979980f, 0.000000f, 0.996094f, 0.015625f, -1.0625f, -29.0625f, 30.0000f, 33, 32}, // 5fb4 + {0.689453f, 0.086914f, 0.705078f, 0.102539f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 5fb3 + {0.317871f, 0.031250f, 0.333984f, 0.046875f, -1.0625f, -29.0625f, 30.0000f, 33, 32}, // 5fb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fb8 - {0.569336f, 0.065430f, 0.584961f, 0.081055f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 5fb9 + {0.387695f, 0.088379f, 0.403320f, 0.104004f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 5fb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fbc @@ -5669,17 +5970,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc2 - {0.732422f, 0.554688f, 0.748047f, 0.568848f, -0.8125f, -28.0625f, 30.0000f, 32, 29}, // 5fc3 + {0.076172f, 0.581055f, 0.091797f, 0.595215f, -0.8125f, -28.0625f, 30.0000f, 32, 29}, // 5fc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc4 - {0.765137f, 0.554688f, 0.780762f, 0.568848f, -0.5000f, -27.8750f, 30.0000f, 32, 29}, // 5fc5 - {0.655273f, 0.367676f, 0.670410f, 0.382813f, -0.8125f, -28.6250f, 30.0000f, 31, 31}, // 5fc6 + {0.122070f, 0.581055f, 0.137695f, 0.595215f, -0.5000f, -27.8750f, 30.0000f, 32, 29}, // 5fc5 + {0.207031f, 0.392578f, 0.222168f, 0.407715f, -0.8125f, -28.6250f, 30.0000f, 31, 31}, // 5fc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fc9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fcb - {0.091309f, 0.555176f, 0.106934f, 0.569336f, -0.6250f, -27.5625f, 30.0000f, 32, 29}, // 5fcc - {0.229492f, 0.555176f, 0.245117f, 0.569336f, -0.8750f, -27.1875f, 30.0000f, 32, 29}, // 5fcd + {0.230469f, 0.583496f, 0.246094f, 0.597656f, -0.6250f, -27.5625f, 30.0000f, 32, 29}, // 5fcc + {0.399902f, 0.584473f, 0.415527f, 0.598633f, -0.8750f, -27.1875f, 30.0000f, 32, 29}, // 5fcd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fd0 @@ -5689,16 +5990,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fd6 - {0.556641f, 0.429199f, 0.572266f, 0.443848f, -0.6250f, -28.8125f, 30.0000f, 32, 30}, // 5fd7 - {0.748535f, 0.429199f, 0.764160f, 0.443848f, -0.5625f, -29.0000f, 30.0000f, 32, 30}, // 5fd8 - {0.703613f, 0.367676f, 0.718750f, 0.382813f, -0.5625f, -28.9375f, 30.0000f, 31, 31}, // 5fd9 + {0.860352f, 0.450195f, 0.875977f, 0.464844f, -0.6250f, -28.8125f, 30.0000f, 32, 30}, // 5fd7 + {0.828613f, 0.450684f, 0.844238f, 0.465332f, -0.5625f, -29.0000f, 30.0000f, 32, 30}, // 5fd8 + {0.479980f, 0.392578f, 0.495117f, 0.407715f, -0.5625f, -28.9375f, 30.0000f, 31, 31}, // 5fd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fdb - {0.063965f, 0.220703f, 0.079590f, 0.235840f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5fdc + {0.746094f, 0.239258f, 0.761719f, 0.254395f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 5fdc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fdf - {0.764648f, 0.429199f, 0.780273f, 0.443848f, -0.3750f, -29.2500f, 30.0000f, 32, 30}, // 5fe0 + {0.891602f, 0.451172f, 0.907227f, 0.465820f, -0.3750f, -29.2500f, 30.0000f, 32, 30}, // 5fe0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fe1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fe2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fe3 @@ -5709,7 +6010,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fe8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fe9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fea - {0.298340f, 0.065918f, 0.313965f, 0.081543f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 5feb + {0.728027f, 0.088379f, 0.743652f, 0.104004f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 5feb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fee @@ -5719,7 +6020,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff4 - {0.422363f, 0.015137f, 0.438477f, 0.030762f, -1.1250f, -29.3750f, 30.0000f, 33, 32}, // 5ff5 + {0.334473f, 0.031250f, 0.350586f, 0.046875f, -1.1250f, -29.3750f, 30.0000f, 33, 32}, // 5ff5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ff8 @@ -5727,11 +6028,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ffa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ffb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ffc - {0.783203f, 0.367676f, 0.798340f, 0.382813f, -0.1250f, -29.3750f, 30.0000f, 31, 31}, // 5ffd + {0.539063f, 0.392578f, 0.554199f, 0.407715f, -0.1250f, -29.3750f, 30.0000f, 31, 31}, // 5ffd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5ffe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 5fff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6000 - {0.492188f, 0.429688f, 0.507813f, 0.444336f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 6001 + {0.346191f, 0.451660f, 0.361816f, 0.466309f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 6001 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6002 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6003 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6004 @@ -5748,31 +6049,31 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 600f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6010 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6011 - {0.601074f, 0.429688f, 0.616699f, 0.444336f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 6012 + {0.694824f, 0.451660f, 0.710449f, 0.466309f, -0.5625f, -28.9375f, 30.0000f, 32, 30}, // 6012 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6013 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6014 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6015 - {0.314453f, 0.065918f, 0.330078f, 0.081543f, -1.3750f, -29.5000f, 30.0000f, 32, 32}, // 6016 + {0.851563f, 0.088379f, 0.867188f, 0.104004f, -1.3750f, -29.5000f, 30.0000f, 32, 32}, // 6016 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6017 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6018 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6019 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 601a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 601b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 601c - {0.887207f, 0.614258f, 0.902344f, 0.628418f, -0.4375f, -27.3750f, 30.0000f, 31, 29}, // 601d + {0.059570f, 0.641602f, 0.074707f, 0.655762f, -0.4375f, -27.3750f, 30.0000f, 31, 29}, // 601d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 601e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 601f - {0.047852f, 0.221191f, 0.063477f, 0.236328f, -0.5000f, -29.4375f, 30.0000f, 32, 31}, // 6020 + {0.762207f, 0.239258f, 0.777832f, 0.254395f, -0.5000f, -29.4375f, 30.0000f, 32, 31}, // 6020 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6021 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6022 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6023 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6024 - {0.080078f, 0.221191f, 0.095703f, 0.236328f, -0.7500f, -29.3125f, 30.0000f, 32, 31}, // 6025 + {0.271484f, 0.239746f, 0.287109f, 0.254883f, -0.7500f, -29.3125f, 30.0000f, 32, 31}, // 6025 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6026 - {0.816895f, 0.367676f, 0.832031f, 0.382813f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 6027 + {0.554688f, 0.392578f, 0.569824f, 0.407715f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 6027 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6028 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6029 - {0.330566f, 0.065918f, 0.346191f, 0.081543f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 602a + {0.867676f, 0.088867f, 0.883301f, 0.104492f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 602a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 602b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 602c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 602d @@ -5789,7 +6090,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6038 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6039 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 603a - {0.499023f, 0.508789f, 0.514160f, 0.523438f, -0.1250f, -28.9375f, 30.0000f, 31, 30}, // 603b + {0.233398f, 0.537109f, 0.248535f, 0.551758f, -0.1250f, -28.9375f, 30.0000f, 31, 30}, // 603b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 603c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 603d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 603e @@ -5805,14 +6106,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6048 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6049 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 604a - {0.855957f, 0.508789f, 0.871094f, 0.523438f, -0.3750f, -29.0000f, 30.0000f, 31, 30}, // 604b + {0.249023f, 0.537109f, 0.264160f, 0.551758f, -0.3750f, -29.0000f, 30.0000f, 31, 30}, // 604b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 604c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 604d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 604e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 604f - {0.902832f, 0.614258f, 0.917969f, 0.628418f, -0.5625f, -27.3125f, 30.0000f, 31, 29}, // 6050 + {0.455078f, 0.641602f, 0.470215f, 0.655762f, -0.5625f, -27.3125f, 30.0000f, 31, 29}, // 6050 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6051 - {0.491211f, 0.065918f, 0.506836f, 0.081543f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 6052 + {0.231934f, 0.090332f, 0.247559f, 0.105957f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 6052 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6053 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6054 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6055 @@ -5828,26 +6129,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 605f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6060 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6061 - {0.335938f, 0.221191f, 0.351563f, 0.236328f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 6062 + {0.241211f, 0.240234f, 0.256836f, 0.255371f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 6062 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6063 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6064 - {0.000000f, 0.172363f, 0.016113f, 0.187500f, -0.9375f, -28.4375f, 30.0000f, 33, 31}, // 6065 + {0.016602f, 0.191406f, 0.032715f, 0.206543f, -0.9375f, -28.4375f, 30.0000f, 33, 31}, // 6065 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6066 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6067 - {0.174316f, 0.223633f, 0.189941f, 0.238770f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 6068 - {0.811523f, 0.429688f, 0.827148f, 0.444336f, -0.6250f, -27.8750f, 30.0000f, 32, 30}, // 6069 + {0.287598f, 0.240234f, 0.303223f, 0.255371f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 6068 + {0.601563f, 0.452148f, 0.617188f, 0.466797f, -0.6250f, -27.8750f, 30.0000f, 32, 30}, // 6069 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 606a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 606b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 606c - {0.368652f, 0.223633f, 0.384277f, 0.238770f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 606d + {0.303711f, 0.240234f, 0.319336f, 0.255371f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 606d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 606e - {0.654785f, 0.223633f, 0.670410f, 0.238770f, -0.7500f, -29.3125f, 30.0000f, 32, 31}, // 606f + {0.319824f, 0.240234f, 0.335449f, 0.255371f, -0.7500f, -29.3125f, 30.0000f, 32, 31}, // 606f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6070 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6071 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6073 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6074 - {0.878906f, 0.367676f, 0.894043f, 0.382813f, -0.6250f, -29.3750f, 30.0000f, 31, 31}, // 6075 + {0.668457f, 0.392578f, 0.683594f, 0.407715f, -0.6250f, -29.3750f, 30.0000f, 31, 31}, // 6075 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6076 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6077 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6078 @@ -5878,7 +6179,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6091 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6092 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6093 - {0.507324f, 0.065918f, 0.522949f, 0.081543f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 6094 + {0.248047f, 0.090332f, 0.263672f, 0.105957f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 6094 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6095 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6096 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6097 @@ -5889,18 +6190,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 609c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 609d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 609e - {0.127441f, 0.224121f, 0.143066f, 0.239258f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 609f - {0.190430f, 0.224121f, 0.206055f, 0.239258f, -1.1875f, -29.1875f, 30.0000f, 32, 31}, // 60a0 + {0.465820f, 0.241211f, 0.481445f, 0.256348f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 609f + {0.498535f, 0.241211f, 0.514160f, 0.256348f, -1.1875f, -29.1875f, 30.0000f, 32, 31}, // 60a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60a2 - {0.561523f, 0.224121f, 0.577148f, 0.239258f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 60a3 + {0.481934f, 0.241699f, 0.497559f, 0.256836f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 60a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60a5 - {0.438965f, 0.015137f, 0.455078f, 0.030762f, -1.3750f, -29.3750f, 30.0000f, 33, 32}, // 60a6 + {0.351074f, 0.031250f, 0.367188f, 0.046875f, -1.3750f, -29.3750f, 30.0000f, 33, 32}, // 60a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60a7 - {0.923340f, 0.429688f, 0.938965f, 0.444336f, -0.5625f, -29.3125f, 30.0000f, 32, 30}, // 60a8 - {0.886719f, 0.508789f, 0.901367f, 0.523926f, -0.8125f, -28.9375f, 30.0000f, 30, 31}, // 60a9 - {0.847656f, 0.555176f, 0.863281f, 0.569336f, -0.1875f, -27.5000f, 30.0000f, 32, 29}, // 60aa + {0.362305f, 0.452637f, 0.377930f, 0.467285f, -0.5625f, -29.3125f, 30.0000f, 32, 30}, // 60a8 + {0.709473f, 0.537598f, 0.724121f, 0.552734f, -0.8125f, -28.9375f, 30.0000f, 30, 31}, // 60a9 + {0.574219f, 0.584473f, 0.589844f, 0.598633f, -0.1875f, -27.5000f, 30.0000f, 32, 29}, // 60aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ad @@ -5908,7 +6209,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b1 - {0.818359f, 0.224121f, 0.833984f, 0.239258f, -0.7500f, -29.0000f, 30.0000f, 32, 31}, // 60b2 + {0.778320f, 0.241699f, 0.793945f, 0.256836f, -0.7500f, -29.0000f, 30.0000f, 32, 31}, // 60b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b5 @@ -5918,7 +6219,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60bb - {0.473145f, 0.066406f, 0.488770f, 0.082031f, -1.3750f, -29.3750f, 30.0000f, 32, 32}, // 60bc + {0.264160f, 0.090332f, 0.279785f, 0.105957f, -1.3750f, -29.3750f, 30.0000f, 32, 32}, // 60bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60bf @@ -5927,7 +6228,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c4 - {0.731445f, 0.066406f, 0.747070f, 0.082031f, -1.4375f, -29.1250f, 30.0000f, 32, 32}, // 60c5 + {0.562500f, 0.090332f, 0.578125f, 0.105957f, -1.4375f, -29.1250f, 30.0000f, 32, 32}, // 60c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60c8 @@ -5939,7 +6240,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60d0 - {0.956543f, 0.429688f, 0.972168f, 0.444336f, -0.5625f, -29.3750f, 30.0000f, 32, 30}, // 60d1 + {0.635254f, 0.452637f, 0.650879f, 0.467285f, -0.5625f, -29.3750f, 30.0000f, 32, 30}, // 60d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60d4 @@ -5950,7 +6251,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60db - {0.523438f, 0.067383f, 0.539063f, 0.083008f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 60dc + {0.578613f, 0.090332f, 0.594238f, 0.105957f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 60dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60df @@ -5962,7 +6263,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60e7 - {0.631836f, 0.016113f, 0.647949f, 0.031738f, -1.0000f, -29.0625f, 30.0000f, 33, 32}, // 60e8 + {0.367676f, 0.031250f, 0.383789f, 0.046875f, -1.0000f, -29.0625f, 30.0000f, 33, 32}, // 60e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60eb @@ -5970,10 +6271,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ef - {0.222168f, 0.067871f, 0.237793f, 0.083496f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 60f0 + {0.705566f, 0.090820f, 0.721191f, 0.106445f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 60f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60f2 - {0.874023f, 0.224121f, 0.889648f, 0.239258f, -0.7500f, -28.8125f, 30.0000f, 32, 31}, // 60f3 + {0.335938f, 0.242188f, 0.351563f, 0.257324f, -0.7500f, -28.8125f, 30.0000f, 32, 31}, // 60f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60f6 @@ -5987,7 +6288,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 60ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6100 - {0.890137f, 0.224121f, 0.905762f, 0.239258f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 6101 + {0.852539f, 0.242676f, 0.868164f, 0.257813f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 6101 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6102 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6103 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6104 @@ -5995,13 +6296,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6106 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6107 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6108 - {0.648438f, 0.016113f, 0.664551f, 0.031738f, -1.1250f, -29.4375f, 30.0000f, 33, 32}, // 6109 + {0.384277f, 0.031250f, 0.400391f, 0.046875f, -1.1250f, -29.4375f, 30.0000f, 33, 32}, // 6109 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 610a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 610b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 610c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 610d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 610e - {0.143555f, 0.224609f, 0.159180f, 0.239746f, -0.7500f, -29.2500f, 30.0000f, 32, 31}, // 610f + {0.368652f, 0.243652f, 0.384277f, 0.258789f, -0.7500f, -29.2500f, 30.0000f, 32, 31}, // 610f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6110 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6111 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6112 @@ -6012,12 +6313,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6117 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6118 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6119 - {0.972656f, 0.429688f, 0.988281f, 0.444336f, -0.8750f, -27.8125f, 30.0000f, 32, 30}, // 611a - {0.096191f, 0.223633f, 0.111328f, 0.239258f, 0.1250f, -29.0625f, 30.0000f, 31, 32}, // 611b + {0.314453f, 0.453613f, 0.330078f, 0.468262f, -0.8750f, -27.8125f, 30.0000f, 32, 30}, // 611a + {0.032227f, 0.240723f, 0.047363f, 0.256348f, 0.1250f, -29.0625f, 30.0000f, 31, 32}, // 611b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 611c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 611d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 611e - {0.187500f, 0.430176f, 0.203125f, 0.444824f, -0.6250f, -28.9375f, 30.0000f, 32, 30}, // 611f + {0.778320f, 0.453613f, 0.793945f, 0.468262f, -0.6250f, -28.9375f, 30.0000f, 32, 30}, // 611f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6120 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6121 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6122 @@ -6058,20 +6359,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6145 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6146 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6147 - {0.530273f, 0.224609f, 0.545898f, 0.239746f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 6148 + {0.888672f, 0.243652f, 0.904297f, 0.258789f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 6148 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6149 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 614a - {0.577637f, 0.224609f, 0.593262f, 0.239746f, -0.5625f, -29.4375f, 30.0000f, 32, 31}, // 614b - {0.238281f, 0.067871f, 0.253906f, 0.083496f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 614c + {0.416016f, 0.244141f, 0.431641f, 0.259277f, -0.5625f, -29.4375f, 30.0000f, 32, 31}, // 614b + {0.744141f, 0.090820f, 0.759766f, 0.106445f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 614c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 614d - {0.254395f, 0.067871f, 0.270020f, 0.083496f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 614e + {0.760254f, 0.090820f, 0.775879f, 0.106445f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 614e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 614f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6150 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6151 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6152 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6153 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6154 - {0.593750f, 0.224609f, 0.609375f, 0.239746f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 6155 + {0.432129f, 0.244141f, 0.447754f, 0.259277f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 6155 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6156 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6157 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6158 @@ -6084,27 +6385,27 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 615f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6160 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6161 - {0.609863f, 0.224609f, 0.625488f, 0.239746f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 6162 - {0.270508f, 0.067871f, 0.286133f, 0.083496f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 6163 + {0.448242f, 0.244141f, 0.463867f, 0.259277f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 6162 + {0.618164f, 0.091309f, 0.633789f, 0.106934f, -0.8125f, -29.3125f, 30.0000f, 32, 32}, // 6163 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6164 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6165 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6166 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6167 - {0.665039f, 0.016113f, 0.681152f, 0.031738f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 6168 + {0.548828f, 0.032715f, 0.564941f, 0.048340f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 6168 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6169 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 616a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 616b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 616c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 616d - {0.379395f, 0.069336f, 0.395020f, 0.084961f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 616e + {0.634277f, 0.091309f, 0.649902f, 0.106934f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 616e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 616f - {0.410645f, 0.430176f, 0.426270f, 0.444824f, -0.3750f, -29.1875f, 30.0000f, 32, 30}, // 6170 + {0.794434f, 0.453613f, 0.810059f, 0.468262f, -0.3750f, -29.1875f, 30.0000f, 32, 30}, // 6170 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6171 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6172 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6173 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6174 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6175 - {0.438477f, 0.072266f, 0.454102f, 0.087891f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 6176 + {0.048340f, 0.091797f, 0.063965f, 0.107422f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 6176 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6177 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6178 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6179 @@ -6116,7 +6417,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 617f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6180 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6181 - {0.687500f, 0.224609f, 0.703125f, 0.239746f, -0.3750f, -28.5000f, 30.0000f, 32, 31}, // 6182 + {0.545898f, 0.244141f, 0.561523f, 0.259277f, -0.3750f, -28.5000f, 30.0000f, 32, 31}, // 6182 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6183 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6184 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6185 @@ -6128,7 +6429,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 618b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 618c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 618d - {0.546387f, 0.224609f, 0.561523f, 0.240234f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 618e + {0.904785f, 0.244141f, 0.919922f, 0.259766f, -0.8750f, -29.0625f, 30.0000f, 31, 32}, // 618e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 618f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6190 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6191 @@ -6150,12 +6451,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a3 - {0.454590f, 0.072754f, 0.470215f, 0.088379f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 61a4 + {0.064453f, 0.091797f, 0.080078f, 0.107422f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 61a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61a8 - {0.703613f, 0.224609f, 0.719238f, 0.239746f, -0.7500f, -29.3750f, 30.0000f, 32, 31}, // 61a9 + {0.920410f, 0.244141f, 0.936035f, 0.259277f, -0.7500f, -29.3750f, 30.0000f, 32, 31}, // 61a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61ac @@ -6164,11 +6465,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b1 - {0.016602f, 0.172363f, 0.032715f, 0.187500f, -0.7500f, -29.1875f, 30.0000f, 33, 31}, // 61b2 + {0.759766f, 0.191895f, 0.775879f, 0.207031f, -0.7500f, -29.1875f, 30.0000f, 33, 31}, // 61b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b5 - {0.128906f, 0.074219f, 0.144531f, 0.089844f, -1.0625f, -29.2500f, 30.0000f, 32, 32}, // 61b6 + {0.080566f, 0.091797f, 0.096191f, 0.107422f, -1.0625f, -29.2500f, 30.0000f, 32, 32}, // 61b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61b9 @@ -6176,7 +6477,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61bd - {0.145020f, 0.074219f, 0.160645f, 0.089844f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 61be + {0.650391f, 0.092285f, 0.666016f, 0.107910f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 61be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c1 @@ -6185,16 +6486,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c6 - {0.738770f, 0.224609f, 0.754395f, 0.239746f, -0.5625f, -29.3750f, 30.0000f, 32, 31}, // 61c7 + {0.955566f, 0.244141f, 0.971191f, 0.259277f, -0.5625f, -29.3750f, 30.0000f, 32, 31}, // 61c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61c8 - {0.346680f, 0.074707f, 0.362305f, 0.090332f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 61c9 + {0.666504f, 0.092285f, 0.682129f, 0.107910f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 61c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61cf - {0.362793f, 0.074707f, 0.378418f, 0.090332f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 61d0 + {0.145020f, 0.093262f, 0.160645f, 0.108887f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 61d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61d3 @@ -6228,13 +6529,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f1 - {0.770508f, 0.224609f, 0.786133f, 0.239746f, -1.0625f, -29.4375f, 30.0000f, 32, 31}, // 61f2 + {0.835449f, 0.244629f, 0.851074f, 0.259766f, -1.0625f, -29.4375f, 30.0000f, 32, 31}, // 61f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f7 - {0.786621f, 0.224609f, 0.802246f, 0.239746f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 61f8 + {0.868652f, 0.244629f, 0.884277f, 0.259766f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 61f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 61fb @@ -6257,16 +6558,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 620c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 620d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 620e - {0.894531f, 0.367676f, 0.909668f, 0.382813f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 620f - {0.719727f, 0.225098f, 0.734863f, 0.240723f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 6210 - {0.189941f, 0.368164f, 0.205078f, 0.383301f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 6211 - {0.754883f, 0.225098f, 0.770020f, 0.240723f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 6212 + {0.046875f, 0.393066f, 0.062012f, 0.408203f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 620f + {0.936523f, 0.244629f, 0.951660f, 0.260254f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 6210 + {0.175293f, 0.393066f, 0.190430f, 0.408203f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 6211 + {0.971680f, 0.244629f, 0.986816f, 0.260254f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 6212 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6213 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6214 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6215 - {0.431152f, 0.368164f, 0.446289f, 0.383301f, 0.0625f, -29.1875f, 30.0000f, 31, 31}, // 6216 + {0.190918f, 0.393066f, 0.206055f, 0.408203f, 0.0625f, -29.1875f, 30.0000f, 31, 31}, // 6216 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6217 - {0.964355f, 0.508789f, 0.979004f, 0.523926f, 1.0000f, -28.8750f, 30.0000f, 30, 31}, // 6218 + {0.407227f, 0.538086f, 0.421875f, 0.553223f, 1.0000f, -28.8750f, 30.0000f, 30, 31}, // 6218 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6219 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 621a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 621b @@ -6280,54 +6581,54 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6223 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6224 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6225 - {0.000000f, 0.075684f, 0.015625f, 0.091309f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 6226 + {0.192383f, 0.093262f, 0.208008f, 0.108887f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 6226 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6227 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6228 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6229 - {0.857910f, 0.225098f, 0.873535f, 0.240234f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 622a + {0.095703f, 0.246582f, 0.111328f, 0.261719f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 622a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 622b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 622c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 622d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 622e - {0.016113f, 0.075684f, 0.031738f, 0.091309f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 622f - {0.906250f, 0.225098f, 0.921387f, 0.240723f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 6230 + {0.208496f, 0.093262f, 0.224121f, 0.108887f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 622f + {0.722656f, 0.247070f, 0.737793f, 0.262695f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 6230 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6231 - {0.032227f, 0.075684f, 0.047852f, 0.091309f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 6232 + {0.161133f, 0.093750f, 0.176758f, 0.109375f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 6232 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6233 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6234 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6235 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6236 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6237 - {0.721191f, 0.646484f, 0.735840f, 0.660645f, -0.3125f, -26.9375f, 30.0000f, 30, 29}, // 6238 + {0.028809f, 0.674805f, 0.043457f, 0.688965f, -0.3125f, -26.9375f, 30.0000f, 30, 29}, // 6238 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6239 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 623a - {0.426758f, 0.430176f, 0.442383f, 0.444824f, -0.8750f, -27.9375f, 30.0000f, 32, 30}, // 623b + {0.046387f, 0.455078f, 0.062012f, 0.469727f, -0.8750f, -27.9375f, 30.0000f, 32, 30}, // 623b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 623c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 623d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 623e - {0.491699f, 0.368164f, 0.506836f, 0.383301f, -0.8125f, -28.1875f, 30.0000f, 31, 31}, // 623f - {0.048340f, 0.077148f, 0.063965f, 0.092773f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 6240 + {0.570313f, 0.393066f, 0.585449f, 0.408203f, -0.8125f, -28.1875f, 30.0000f, 31, 31}, // 623f + {0.000000f, 0.094727f, 0.015625f, 0.110352f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 6240 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6241 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6242 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6243 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6244 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6245 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6246 - {0.979492f, 0.508789f, 0.994141f, 0.523926f, -1.0000f, -28.3750f, 30.0000f, 30, 31}, // 6247 + {0.577148f, 0.538086f, 0.591797f, 0.553223f, -1.0000f, -28.3750f, 30.0000f, 30, 31}, // 6247 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6248 - {0.921875f, 0.225098f, 0.937500f, 0.240234f, -1.1875f, -28.3125f, 30.0000f, 32, 31}, // 6249 + {0.384766f, 0.247559f, 0.400391f, 0.262695f, -1.1875f, -28.3125f, 30.0000f, 32, 31}, // 6249 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 624a - {0.123047f, 0.555176f, 0.137207f, 0.570801f, 0.5625f, -29.0000f, 30.0000f, 29, 32}, // 624b + {0.015137f, 0.581055f, 0.029297f, 0.596680f, 0.5625f, -29.0000f, 30.0000f, 29, 32}, // 624b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 624c - {0.247070f, 0.509277f, 0.261719f, 0.524414f, -0.0625f, -29.0625f, 30.0000f, 30, 31}, // 624d + {0.691406f, 0.538086f, 0.706055f, 0.553223f, -0.0625f, -29.0625f, 30.0000f, 30, 31}, // 624d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 624e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 624f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6250 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6251 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6252 - {0.253418f, 0.368652f, 0.268555f, 0.383789f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 6253 + {0.142578f, 0.393555f, 0.157715f, 0.408691f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 6253 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6254 - {0.937988f, 0.225098f, 0.953613f, 0.240234f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 6255 + {0.626953f, 0.247559f, 0.642578f, 0.262695f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 6255 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6256 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6257 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6258 @@ -6345,7 +6646,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6264 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6265 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6266 - {0.954102f, 0.225098f, 0.969727f, 0.240234f, -1.3125f, -28.7500f, 30.0000f, 32, 31}, // 6267 + {0.661621f, 0.248047f, 0.677246f, 0.263184f, -1.3125f, -28.7500f, 30.0000f, 32, 31}, // 6267 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6268 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6269 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 626a @@ -6355,83 +6656,83 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 626e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 626f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6270 - {0.448730f, 0.225586f, 0.464355f, 0.240723f, -0.8125f, -29.2500f, 30.0000f, 32, 31}, // 6271 + {0.352051f, 0.249023f, 0.367676f, 0.264160f, -0.8125f, -29.2500f, 30.0000f, 32, 31}, // 6271 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6273 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6274 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6275 - {0.064453f, 0.077148f, 0.080078f, 0.092773f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6276 + {0.016113f, 0.094727f, 0.031738f, 0.110352f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6276 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6277 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6278 - {0.497559f, 0.225586f, 0.513184f, 0.240723f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 6279 + {0.794434f, 0.249512f, 0.810059f, 0.264648f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 6279 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 627a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 627b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 627c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 627d - {0.205566f, 0.369141f, 0.220703f, 0.384277f, -0.1250f, -28.7500f, 30.0000f, 31, 31}, // 627e - {0.473145f, 0.430176f, 0.488770f, 0.444824f, -1.0625f, -27.5625f, 30.0000f, 32, 30}, // 627f - {0.802734f, 0.225586f, 0.818359f, 0.240723f, -0.9375f, -28.7500f, 30.0000f, 32, 31}, // 6280 + {0.585938f, 0.393555f, 0.601074f, 0.408691f, -0.1250f, -28.7500f, 30.0000f, 31, 31}, // 627e + {0.490234f, 0.455078f, 0.505859f, 0.469727f, -1.0625f, -27.5625f, 30.0000f, 32, 30}, // 627f + {0.810547f, 0.249512f, 0.826172f, 0.264648f, -0.9375f, -28.7500f, 30.0000f, 32, 31}, // 6280 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6281 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6282 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6283 - {0.834473f, 0.225586f, 0.850098f, 0.240723f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 6284 + {0.205566f, 0.250488f, 0.221191f, 0.265625f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 6284 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6285 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6286 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6287 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6288 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6289 - {0.970215f, 0.225586f, 0.985840f, 0.240723f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 628a + {0.514648f, 0.250488f, 0.530273f, 0.265625f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 628a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 628b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 628c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 628d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 628e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 628f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6290 - {0.859863f, 0.429199f, 0.874512f, 0.444824f, -0.6250f, -29.0625f, 30.0000f, 30, 32}, // 6291 + {0.094238f, 0.451172f, 0.108887f, 0.466797f, -0.6250f, -29.0625f, 30.0000f, 30, 32}, // 6291 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6292 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6293 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6294 - {0.273926f, 0.226074f, 0.289551f, 0.241211f, -0.3125f, -28.6250f, 30.0000f, 32, 31}, // 6295 + {0.221680f, 0.250977f, 0.237305f, 0.266113f, -0.3125f, -28.6250f, 30.0000f, 32, 31}, // 6295 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6296 - {0.290039f, 0.226074f, 0.305664f, 0.241211f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 6297 - {0.384766f, 0.226074f, 0.399902f, 0.241699f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 6298 + {0.643066f, 0.250977f, 0.658691f, 0.266113f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 6297 + {0.400879f, 0.247559f, 0.416016f, 0.263184f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 6298 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6299 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 629a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 629b - {0.080566f, 0.077148f, 0.096191f, 0.092773f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 629c + {0.032227f, 0.094727f, 0.047852f, 0.110352f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 629c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 629d - {0.464844f, 0.226074f, 0.480469f, 0.241211f, -0.8125f, -29.1875f, 30.0000f, 32, 31}, // 629e + {0.706543f, 0.250977f, 0.722168f, 0.266113f, -0.8125f, -29.1875f, 30.0000f, 32, 31}, // 629e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 629f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a4 - {0.221191f, 0.369141f, 0.236328f, 0.384277f, -0.5625f, -28.6250f, 30.0000f, 31, 31}, // 62a5 + {0.079590f, 0.394043f, 0.094727f, 0.409180f, -0.5625f, -28.6250f, 30.0000f, 31, 31}, // 62a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62aa - {0.681641f, 0.016113f, 0.697754f, 0.031738f, -0.6875f, -29.0000f, 30.0000f, 33, 32}, // 62ab + {0.565430f, 0.032715f, 0.581543f, 0.048340f, -0.6875f, -29.0000f, 30.0000f, 33, 32}, // 62ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b0 - {0.513672f, 0.226074f, 0.529297f, 0.241211f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 62b1 + {0.562012f, 0.251465f, 0.577637f, 0.266602f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 62b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b4 - {0.625977f, 0.226074f, 0.641602f, 0.241211f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 62b5 + {0.578125f, 0.251465f, 0.593750f, 0.266602f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 62b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62b8 - {0.096680f, 0.077148f, 0.112305f, 0.092773f, -0.1875f, -29.0625f, 30.0000f, 32, 32}, // 62b9 + {0.794922f, 0.095215f, 0.810547f, 0.110840f, -0.1875f, -29.0625f, 30.0000f, 32, 32}, // 62b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62bb - {0.372559f, 0.509277f, 0.387207f, 0.524414f, 0.1875f, -28.8750f, 30.0000f, 30, 31}, // 62bc - {0.125488f, 0.429688f, 0.140137f, 0.445313f, -0.1875f, -29.1250f, 30.0000f, 30, 32}, // 62bd + {0.000000f, 0.538574f, 0.014648f, 0.553711f, 0.1875f, -28.8750f, 30.0000f, 30, 31}, // 62bc + {0.617676f, 0.455078f, 0.632324f, 0.470703f, -0.1875f, -29.1250f, 30.0000f, 30, 32}, // 62bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c0 @@ -6439,35 +6740,35 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c4 - {0.258301f, 0.226563f, 0.273926f, 0.241699f, -0.6875f, -29.1250f, 30.0000f, 32, 31}, // 62c5 + {0.677734f, 0.251465f, 0.693359f, 0.266602f, -0.6875f, -29.1250f, 30.0000f, 32, 31}, // 62c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62c8 - {0.399414f, 0.369141f, 0.414551f, 0.384277f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 62c9 + {0.601563f, 0.394043f, 0.616699f, 0.409180f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 62c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62cc - {0.932617f, 0.555176f, 0.946777f, 0.570801f, 0.1875f, -29.5625f, 30.0000f, 29, 32}, // 62cd + {0.138184f, 0.581055f, 0.152344f, 0.596680f, 0.1875f, -29.5625f, 30.0000f, 29, 32}, // 62cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62cf - {0.437500f, 0.509277f, 0.452148f, 0.524414f, -0.5625f, -28.8125f, 30.0000f, 30, 31}, // 62d0 + {0.214844f, 0.538574f, 0.229492f, 0.553711f, -0.5625f, -28.8125f, 30.0000f, 30, 31}, // 62d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62d1 - {0.112793f, 0.079102f, 0.128418f, 0.094727f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 62d2 - {0.446777f, 0.369141f, 0.461914f, 0.384277f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 62d3 + {0.811035f, 0.095215f, 0.826660f, 0.110840f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 62d2 + {0.062500f, 0.394531f, 0.077637f, 0.409668f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 62d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62d7 - {0.508301f, 0.429688f, 0.522949f, 0.445313f, -0.1250f, -29.5000f, 30.0000f, 30, 32}, // 62d8 - {0.452637f, 0.509277f, 0.467285f, 0.524414f, -0.2500f, -29.0000f, 30.0000f, 30, 31}, // 62d9 + {0.678711f, 0.455078f, 0.693359f, 0.470703f, -0.1250f, -29.5000f, 30.0000f, 30, 32}, // 62d8 + {0.422363f, 0.538574f, 0.437012f, 0.553711f, -0.2500f, -29.0000f, 30.0000f, 30, 31}, // 62d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62da - {0.919434f, 0.509277f, 0.934082f, 0.524414f, 0.0000f, -28.6250f, 30.0000f, 30, 31}, // 62db + {0.437500f, 0.538574f, 0.452148f, 0.553711f, 0.0000f, -28.6250f, 30.0000f, 30, 31}, // 62db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62dc - {0.161133f, 0.079590f, 0.176758f, 0.095215f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 62dd + {0.306641f, 0.095703f, 0.322266f, 0.111328f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 62dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62de - {0.462402f, 0.369141f, 0.477539f, 0.384277f, -0.8125f, -28.9375f, 30.0000f, 31, 31}, // 62df - {0.670898f, 0.226563f, 0.686523f, 0.241699f, -0.3750f, -29.0000f, 30.0000f, 32, 31}, // 62e0 - {0.432129f, 0.227051f, 0.447754f, 0.242188f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 62e1 + {0.111816f, 0.394531f, 0.126953f, 0.409668f, -0.8125f, -28.9375f, 30.0000f, 31, 31}, // 62df + {0.047852f, 0.251953f, 0.063477f, 0.267090f, -0.3750f, -29.0000f, 30.0000f, 32, 31}, // 62e0 + {0.063965f, 0.252441f, 0.079590f, 0.267578f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 62e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e4 @@ -6475,10 +6776,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62e8 - {0.480957f, 0.227051f, 0.496582f, 0.242188f, -1.1250f, -28.8125f, 30.0000f, 32, 31}, // 62e9 + {0.080078f, 0.252441f, 0.095703f, 0.267578f, -1.1250f, -28.8125f, 30.0000f, 32, 31}, // 62e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62eb - {0.205566f, 0.079590f, 0.221191f, 0.095215f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 62ec + {0.322754f, 0.095703f, 0.338379f, 0.111328f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 62ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ef @@ -6489,25 +6790,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62f6 - {0.206543f, 0.227539f, 0.222168f, 0.242676f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 62f7 + {0.594238f, 0.252441f, 0.609863f, 0.267578f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 62f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62fd - {0.395508f, 0.079590f, 0.411133f, 0.095215f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 62fe + {0.338867f, 0.095703f, 0.354492f, 0.111328f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 62fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 62ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6300 - {0.242676f, 0.228027f, 0.258301f, 0.243164f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 6301 + {0.610352f, 0.252441f, 0.625977f, 0.267578f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 6301 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6302 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6303 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6304 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6305 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6306 - {0.302246f, 0.371582f, 0.317383f, 0.386719f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 6307 + {0.158203f, 0.395020f, 0.173340f, 0.410156f, -0.5000f, -28.8750f, 30.0000f, 31, 31}, // 6307 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6308 - {0.366699f, 0.374023f, 0.381836f, 0.389160f, -0.3125f, -29.0000f, 30.0000f, 31, 31}, // 6309 + {0.000000f, 0.395508f, 0.015137f, 0.410645f, -0.3125f, -29.0000f, 30.0000f, 31, 31}, // 6309 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 630a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 630b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 630c @@ -6515,7 +6816,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 630e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 630f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6310 - {0.411621f, 0.079590f, 0.427246f, 0.095215f, -0.6250f, -28.7500f, 30.0000f, 32, 32}, // 6311 + {0.354980f, 0.095703f, 0.370605f, 0.111328f, -0.6250f, -28.7500f, 30.0000f, 32, 32}, // 6311 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6312 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6313 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6314 @@ -6523,13 +6824,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6316 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6317 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6318 - {0.711426f, 0.079590f, 0.727051f, 0.095215f, -1.4375f, -29.0625f, 30.0000f, 32, 32}, // 6319 + {0.371094f, 0.095703f, 0.386719f, 0.111328f, -1.4375f, -29.0625f, 30.0000f, 32, 32}, // 6319 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 631a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 631b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 631c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 631d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 631e - {0.222656f, 0.228516f, 0.238281f, 0.243652f, -1.2500f, -28.9375f, 30.0000f, 32, 31}, // 631f + {0.157227f, 0.252930f, 0.172852f, 0.268066f, -1.2500f, -28.9375f, 30.0000f, 32, 31}, // 631f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6320 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6321 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6322 @@ -6545,7 +6846,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 632c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 632d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 632e - {0.352051f, 0.229980f, 0.367676f, 0.245117f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 632f + {0.173340f, 0.252930f, 0.188965f, 0.268066f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 632f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6330 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6331 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6332 @@ -6561,7 +6862,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 633c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 633d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 633e - {0.382324f, 0.374512f, 0.397461f, 0.389648f, -0.1875f, -29.3750f, 30.0000f, 31, 31}, // 633f + {0.015625f, 0.395508f, 0.030762f, 0.410645f, -0.1875f, -29.3750f, 30.0000f, 31, 31}, // 633f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6340 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6341 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6342 @@ -6583,32 +6884,32 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6352 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6353 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6354 - {0.177246f, 0.080078f, 0.192871f, 0.095703f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 6355 + {0.280273f, 0.096191f, 0.295898f, 0.111816f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 6355 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6356 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6357 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6358 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6359 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 635a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 635b - {0.585449f, 0.080566f, 0.601074f, 0.096191f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 635c + {0.520508f, 0.097168f, 0.536133f, 0.112793f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 635c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 635d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 635e - {0.400391f, 0.232910f, 0.416016f, 0.248047f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 635f + {0.111816f, 0.253418f, 0.127441f, 0.268555f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 635f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6360 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6361 - {0.111816f, 0.233398f, 0.127441f, 0.248535f, -1.3125f, -28.8125f, 30.0000f, 32, 31}, // 6362 + {0.127930f, 0.253418f, 0.143555f, 0.268555f, -1.3125f, -28.8125f, 30.0000f, 32, 31}, // 6362 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6363 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6364 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6365 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6366 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6367 - {0.601563f, 0.080566f, 0.617188f, 0.096191f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 6368 + {0.536621f, 0.097168f, 0.552246f, 0.112793f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 6368 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6369 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 636a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 636b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 636c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 636d - {0.416504f, 0.233398f, 0.432129f, 0.248535f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 636e + {0.189453f, 0.253418f, 0.205078f, 0.268555f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 636e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 636f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6370 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6371 @@ -6617,7 +6918,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6374 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6375 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6376 - {0.617676f, 0.080566f, 0.633301f, 0.096191f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6377 + {0.827148f, 0.097168f, 0.842773f, 0.112793f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6377 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6378 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6379 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 637a @@ -6629,46 +6930,46 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6380 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6381 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6382 - {0.110352f, 0.375000f, 0.125488f, 0.390137f, -0.6875f, -28.9375f, 30.0000f, 31, 31}, // 6383 + {0.127441f, 0.395508f, 0.142578f, 0.410645f, -0.6875f, -28.9375f, 30.0000f, 31, 31}, // 6383 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6384 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6385 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6386 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6387 - {0.633789f, 0.080566f, 0.649414f, 0.096191f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6388 + {0.903320f, 0.098633f, 0.918945f, 0.114258f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6388 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6389 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 638a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 638b - {0.695313f, 0.509766f, 0.709961f, 0.524902f, 0.3750f, -29.0625f, 30.0000f, 30, 31}, // 638c + {0.724609f, 0.538574f, 0.739258f, 0.553711f, 0.3750f, -29.0625f, 30.0000f, 30, 31}, // 638c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 638d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 638e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 638f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6390 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6391 - {0.306152f, 0.233887f, 0.321777f, 0.249023f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 6392 + {0.015625f, 0.253906f, 0.031250f, 0.269043f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 6392 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6393 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6394 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6395 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6396 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6397 - {0.905273f, 0.430176f, 0.919922f, 0.445801f, -0.5625f, -28.8750f, 30.0000f, 30, 32}, // 6398 + {0.762207f, 0.455078f, 0.776855f, 0.470703f, -0.5625f, -28.8750f, 30.0000f, 30, 32}, // 6398 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6399 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 639a - {0.000000f, 0.234863f, 0.015625f, 0.250000f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 639b + {0.000000f, 0.254883f, 0.015625f, 0.270020f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 639b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 639c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 639d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 639e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 639f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63a0 - {0.698242f, 0.016113f, 0.714355f, 0.031738f, -0.8750f, -29.5000f, 30.0000f, 33, 32}, // 63a1 - {0.016113f, 0.235840f, 0.031738f, 0.250977f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 63a2 + {0.859375f, 0.032715f, 0.875488f, 0.048340f, -0.8750f, -29.5000f, 30.0000f, 33, 32}, // 63a1 + {0.738281f, 0.254883f, 0.753906f, 0.270020f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 63a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63a4 - {0.063965f, 0.236328f, 0.079590f, 0.251465f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 63a5 + {0.754395f, 0.254883f, 0.770020f, 0.270020f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 63a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63a6 - {0.032227f, 0.236816f, 0.047852f, 0.251953f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 63a7 - {0.649902f, 0.080566f, 0.665527f, 0.096191f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 63a8 + {0.257324f, 0.255371f, 0.272949f, 0.270508f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 63a7 + {0.403809f, 0.100098f, 0.419434f, 0.115723f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 63a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63a9 - {0.000000f, 0.375977f, 0.015137f, 0.391113f, -0.5625f, -28.7500f, 30.0000f, 31, 31}, // 63aa + {0.735352f, 0.396484f, 0.750488f, 0.411621f, -0.5625f, -28.7500f, 30.0000f, 31, 31}, // 63aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ad @@ -6676,7 +6977,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63b1 - {0.871582f, 0.509766f, 0.886230f, 0.524902f, 0.1875f, -28.5625f, 30.0000f, 30, 31}, // 63b2 + {0.169434f, 0.539063f, 0.184082f, 0.554199f, 0.1875f, -28.5625f, 30.0000f, 30, 31}, // 63b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63b5 @@ -6705,10 +7006,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ce - {0.048340f, 0.236816f, 0.063965f, 0.251953f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 63cf - {0.080078f, 0.236816f, 0.095703f, 0.251953f, -0.5625f, -28.8125f, 30.0000f, 32, 31}, // 63d0 + {0.237793f, 0.255859f, 0.253418f, 0.270996f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 63cf + {0.273438f, 0.255859f, 0.289063f, 0.270996f, -0.5625f, -28.8125f, 30.0000f, 32, 31}, // 63d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d1 - {0.322266f, 0.236816f, 0.337402f, 0.252441f, -0.6250f, -29.1250f, 30.0000f, 31, 32}, // 63d2 + {0.530762f, 0.250488f, 0.545898f, 0.266113f, -0.6250f, -29.1250f, 30.0000f, 31, 32}, // 63d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d5 @@ -6716,14 +7017,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63d9 - {0.015625f, 0.377441f, 0.030762f, 0.392578f, -0.6250f, -28.6250f, 30.0000f, 31, 31}, // 63da - {0.666016f, 0.080566f, 0.681641f, 0.096191f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 63db + {0.222656f, 0.396973f, 0.237793f, 0.412109f, -0.6250f, -28.6250f, 30.0000f, 31, 31}, // 63da + {0.453613f, 0.100098f, 0.469238f, 0.115723f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 63db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63e0 - {0.046875f, 0.377930f, 0.062012f, 0.393066f, -0.4375f, -28.9375f, 30.0000f, 31, 31}, // 63e1 + {0.253418f, 0.396973f, 0.268555f, 0.412109f, -0.4375f, -28.9375f, 30.0000f, 31, 31}, // 63e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63e4 @@ -6736,19 +7037,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ed - {0.062500f, 0.378418f, 0.077637f, 0.393555f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 63ee + {0.718750f, 0.396973f, 0.733887f, 0.412109f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 63ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f3 - {0.159668f, 0.239258f, 0.175293f, 0.254395f, -0.1875f, -28.9375f, 30.0000f, 32, 31}, // 63f4 + {0.289551f, 0.255859f, 0.305176f, 0.270996f, -0.1875f, -28.9375f, 30.0000f, 32, 31}, // 63f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63f9 - {0.031250f, 0.378906f, 0.046387f, 0.394043f, -0.8750f, -28.6250f, 30.0000f, 31, 31}, // 63fa + {0.269043f, 0.397461f, 0.284180f, 0.412598f, -0.8750f, -28.6250f, 30.0000f, 31, 31}, // 63fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 63fd @@ -6767,7 +7068,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 640a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 640b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 640c - {0.368164f, 0.239258f, 0.383789f, 0.254395f, -0.5000f, -28.6875f, 30.0000f, 32, 31}, // 640d + {0.305664f, 0.255859f, 0.321289f, 0.270996f, -0.5000f, -28.6875f, 30.0000f, 32, 31}, // 640d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 640e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 640f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6410 @@ -6776,7 +7077,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6413 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6414 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6415 - {0.747559f, 0.080566f, 0.763184f, 0.096191f, -0.8125f, -29.3750f, 30.0000f, 32, 32}, // 6416 + {0.469727f, 0.100098f, 0.485352f, 0.115723f, -0.8125f, -29.3750f, 30.0000f, 32, 32}, // 6416 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6417 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6418 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6419 @@ -6798,8 +7099,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6429 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 642a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 642b - {0.714844f, 0.016113f, 0.730957f, 0.031738f, -0.8750f, -29.1875f, 30.0000f, 33, 32}, // 642c - {0.763672f, 0.080566f, 0.779297f, 0.096191f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 642d + {0.615234f, 0.035156f, 0.631348f, 0.050781f, -0.8750f, -29.1875f, 30.0000f, 33, 32}, // 642c + {0.485840f, 0.100098f, 0.501465f, 0.115723f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 642d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 642e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 642f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6430 @@ -6812,20 +7113,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6437 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6438 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6439 - {0.779785f, 0.080566f, 0.795410f, 0.096191f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 643a + {0.501953f, 0.100098f, 0.517578f, 0.115723f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 643a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 643b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 643c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 643d - {0.642090f, 0.239258f, 0.657715f, 0.254395f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 643e + {0.031738f, 0.256836f, 0.047363f, 0.271973f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 643e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 643f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6440 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6441 - {0.096191f, 0.239746f, 0.111816f, 0.254883f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6442 + {0.464355f, 0.256836f, 0.479980f, 0.271973f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6442 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6443 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6444 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6445 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6446 - {0.286133f, 0.379883f, 0.301270f, 0.395020f, -1.1875f, -28.5625f, 30.0000f, 31, 31}, // 6447 + {0.238281f, 0.398438f, 0.253418f, 0.413574f, -1.1875f, -28.5625f, 30.0000f, 31, 31}, // 6447 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6448 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6449 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 644a @@ -6842,7 +7143,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6455 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6456 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6457 - {0.795898f, 0.080566f, 0.811523f, 0.096191f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 6458 + {0.594727f, 0.100098f, 0.610352f, 0.115723f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 6458 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6459 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 645a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 645b @@ -6859,7 +7160,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6466 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6467 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6468 - {0.812012f, 0.080566f, 0.827637f, 0.096191f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 6469 + {0.949707f, 0.100098f, 0.965332f, 0.115723f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 6469 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 646a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 646b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 646c @@ -6874,7 +7175,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6475 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6476 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6477 - {0.127930f, 0.239746f, 0.143555f, 0.254883f, -0.6875f, -28.7500f, 30.0000f, 32, 31}, // 6478 + {0.498047f, 0.256836f, 0.513672f, 0.271973f, -0.6875f, -28.7500f, 30.0000f, 32, 31}, // 6478 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6479 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 647a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 647b @@ -6885,7 +7186,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6480 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6481 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6482 - {0.832520f, 0.379883f, 0.847656f, 0.395020f, 0.1875f, -29.0625f, 30.0000f, 31, 31}, // 6483 + {0.031250f, 0.398926f, 0.046387f, 0.414063f, 0.1875f, -29.0625f, 30.0000f, 31, 31}, // 6483 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6484 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6485 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6486 @@ -6918,7 +7219,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a3 - {0.828125f, 0.080566f, 0.843750f, 0.096191f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 64a4 + {0.965820f, 0.100098f, 0.981445f, 0.115723f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 64a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64a7 @@ -6928,11 +7229,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ad - {0.175781f, 0.239746f, 0.191406f, 0.254883f, -1.0625f, -29.0000f, 30.0000f, 32, 31}, // 64ae + {0.480469f, 0.257324f, 0.496094f, 0.272461f, -1.0625f, -29.0000f, 30.0000f, 32, 31}, // 64ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64b1 - {0.731445f, 0.016113f, 0.747559f, 0.031738f, -0.9375f, -29.0625f, 30.0000f, 33, 32}, // 64b2 + {0.935059f, 0.035156f, 0.951172f, 0.050781f, -0.9375f, -29.0625f, 30.0000f, 33, 32}, // 64b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64b5 @@ -6947,19 +7248,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c0 - {0.844238f, 0.080566f, 0.859863f, 0.096191f, -1.0625f, -29.0625f, 30.0000f, 32, 32}, // 64c1 + {0.981934f, 0.100098f, 0.997559f, 0.115723f, -1.0625f, -29.0625f, 30.0000f, 32, 32}, // 64c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c6 - {0.848145f, 0.379883f, 0.863281f, 0.395020f, -0.5625f, -28.6875f, 30.0000f, 31, 31}, // 64c7 + {0.429688f, 0.398926f, 0.444824f, 0.414063f, -0.5625f, -28.6875f, 30.0000f, 31, 31}, // 64c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64cc - {0.562012f, 0.239746f, 0.577637f, 0.254883f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 64cd + {0.770508f, 0.257324f, 0.786133f, 0.272461f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 64cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64d0 @@ -6972,7 +7273,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64d9 - {0.876953f, 0.080566f, 0.892578f, 0.096191f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 64da + {0.883789f, 0.100586f, 0.899414f, 0.116211f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 64da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64dd @@ -6984,13 +7285,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e5 - {0.818848f, 0.239746f, 0.834473f, 0.254883f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 64e6 + {0.321777f, 0.257813f, 0.337402f, 0.272949f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 64e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64eb - {0.874023f, 0.239746f, 0.889648f, 0.254883f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 64ec + {0.851563f, 0.258301f, 0.867188f, 0.273438f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 64ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 64ef @@ -7057,7 +7358,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 652c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 652d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 652e - {0.158691f, 0.380859f, 0.173828f, 0.395996f, 0.3125f, -28.9375f, 30.0000f, 31, 31}, // 652f + {0.445313f, 0.398926f, 0.460449f, 0.414063f, 0.3125f, -28.9375f, 30.0000f, 31, 31}, // 652f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6530 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6531 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6532 @@ -7067,39 +7368,39 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6536 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6537 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6538 - {0.200195f, 0.510254f, 0.214844f, 0.525391f, 1.0625f, -28.8125f, 30.0000f, 30, 31}, // 6539 + {0.831055f, 0.539551f, 0.845703f, 0.554688f, 1.0625f, -28.8125f, 30.0000f, 30, 31}, // 6539 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 653a - {0.890137f, 0.239746f, 0.905273f, 0.255371f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 653b + {0.368164f, 0.259277f, 0.383301f, 0.274902f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 653b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 653c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 653d - {0.893066f, 0.080566f, 0.908691f, 0.096191f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 653e - {0.909180f, 0.080566f, 0.924805f, 0.096191f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 653f + {0.919434f, 0.101074f, 0.935059f, 0.116699f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 653e + {0.096680f, 0.102051f, 0.112305f, 0.117676f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 653f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6540 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6541 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6542 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6543 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6544 - {0.925293f, 0.080566f, 0.940918f, 0.096191f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 6545 + {0.112793f, 0.102051f, 0.128418f, 0.117676f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 6545 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6546 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6547 - {0.174316f, 0.380859f, 0.189453f, 0.395996f, -0.2500f, -29.0625f, 30.0000f, 31, 31}, // 6548 + {0.750977f, 0.398926f, 0.766113f, 0.414063f, -0.2500f, -29.0625f, 30.0000f, 31, 31}, // 6548 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6549 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 654a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 654b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 654c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 654d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 654e - {0.941406f, 0.080566f, 0.957031f, 0.096191f, -0.3125f, -29.1875f, 30.0000f, 32, 32}, // 654f + {0.128906f, 0.102539f, 0.144531f, 0.118164f, -0.3125f, -29.1875f, 30.0000f, 32, 32}, // 654f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6550 - {0.957520f, 0.080566f, 0.973145f, 0.096191f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 6551 + {0.776367f, 0.102539f, 0.791992f, 0.118164f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 6551 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6552 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6553 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6554 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6555 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6556 - {0.973633f, 0.080566f, 0.989258f, 0.096191f, -0.1250f, -29.1250f, 30.0000f, 32, 32}, // 6557 + {0.419922f, 0.103027f, 0.435547f, 0.118652f, -0.1250f, -29.1250f, 30.0000f, 32, 32}, // 6557 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6558 - {0.144043f, 0.240234f, 0.159668f, 0.255371f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 6559 + {0.884766f, 0.259277f, 0.900391f, 0.274414f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 6559 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 655a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 655b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 655c @@ -7108,8 +7409,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 655f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6560 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6561 - {0.529785f, 0.240234f, 0.545410f, 0.255371f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 6562 - {0.578125f, 0.240234f, 0.593262f, 0.255859f, -0.0625f, -29.0000f, 30.0000f, 31, 32}, // 6563 + {0.416504f, 0.259766f, 0.432129f, 0.274902f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 6562 + {0.432617f, 0.259766f, 0.447754f, 0.275391f, -0.0625f, -29.0000f, 30.0000f, 31, 32}, // 6563 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6564 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6565 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6566 @@ -7118,19 +7419,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6569 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 656a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 656b - {0.539551f, 0.081055f, 0.555176f, 0.096680f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 656c + {0.436035f, 0.103027f, 0.451660f, 0.118652f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 656c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 656d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 656e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 656f - {0.593750f, 0.240234f, 0.609375f, 0.255371f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 6570 + {0.448242f, 0.259766f, 0.463867f, 0.274902f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 6570 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6571 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6572 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6573 - {0.291504f, 0.511719f, 0.306641f, 0.526367f, -0.5000f, -29.2500f, 30.0000f, 31, 30}, // 6574 - {0.682129f, 0.081055f, 0.697754f, 0.096680f, -0.1875f, -29.0625f, 30.0000f, 32, 32}, // 6575 + {0.499023f, 0.540039f, 0.514160f, 0.554688f, -0.5000f, -29.2500f, 30.0000f, 31, 30}, // 6574 + {0.682617f, 0.103027f, 0.698242f, 0.118652f, -0.1875f, -29.0625f, 30.0000f, 32, 32}, // 6575 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6576 - {0.860352f, 0.081055f, 0.875977f, 0.096680f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 6577 - {0.555664f, 0.081543f, 0.571289f, 0.097168f, -0.2500f, -29.0000f, 30.0000f, 32, 32}, // 6578 + {0.387207f, 0.104492f, 0.402832f, 0.120117f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 6577 + {0.721680f, 0.104492f, 0.737305f, 0.120117f, -0.2500f, -29.0000f, 30.0000f, 32, 32}, // 6578 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6579 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 657a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 657b @@ -7145,14 +7446,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6584 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6585 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6586 - {0.560059f, 0.380859f, 0.575195f, 0.395996f, -0.1875f, -28.6875f, 30.0000f, 31, 31}, // 6587 + {0.460938f, 0.399414f, 0.476074f, 0.414551f, -0.1875f, -28.6875f, 30.0000f, 31, 31}, // 6587 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6588 - {0.609863f, 0.240234f, 0.625488f, 0.255371f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 6589 + {0.546387f, 0.259766f, 0.562012f, 0.274902f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 6589 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 658a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 658b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 658c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 658d - {0.033203f, 0.173828f, 0.049316f, 0.188965f, -1.1875f, -28.8750f, 30.0000f, 33, 31}, // 658e + {0.776367f, 0.191895f, 0.792480f, 0.207031f, -1.1875f, -28.8750f, 30.0000f, 33, 31}, // 658e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 658f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6590 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6591 @@ -7161,12 +7462,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6594 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6595 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6596 - {0.078125f, 0.381348f, 0.093262f, 0.396484f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 6597 + {0.284668f, 0.399902f, 0.299805f, 0.415039f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 6597 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6598 - {0.286621f, 0.082031f, 0.302246f, 0.097656f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 6599 + {0.843262f, 0.104492f, 0.858887f, 0.120117f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 6599 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 659a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 659b - {0.302734f, 0.082031f, 0.318359f, 0.097656f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 659c + {0.859375f, 0.104980f, 0.875000f, 0.120605f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 659c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 659d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 659e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 659f @@ -7174,8 +7475,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a3 - {0.947266f, 0.555176f, 0.961426f, 0.570801f, 0.2500f, -29.0000f, 30.0000f, 29, 32}, // 65a4 - {0.961914f, 0.555176f, 0.976074f, 0.570801f, 0.4375f, -29.0000f, 30.0000f, 29, 32}, // 65a5 + {0.737305f, 0.581543f, 0.751465f, 0.597168f, 0.2500f, -29.0000f, 30.0000f, 29, 32}, // 65a4 + {0.703125f, 0.584473f, 0.717285f, 0.600098f, 0.4375f, -29.0000f, 30.0000f, 29, 32}, // 65a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65a8 @@ -7183,10 +7484,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ac - {0.341797f, 0.514160f, 0.356445f, 0.529297f, 0.9375f, -28.7500f, 30.0000f, 30, 31}, // 65ad + {0.909668f, 0.540039f, 0.924316f, 0.555176f, 0.9375f, -28.7500f, 30.0000f, 30, 31}, // 65ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65af - {0.317871f, 0.381348f, 0.333008f, 0.396484f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 65b0 + {0.816895f, 0.399902f, 0.832031f, 0.415039f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 65b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b3 @@ -7195,11 +7496,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65b8 - {0.592285f, 0.381348f, 0.607422f, 0.396484f, -0.5000f, -28.6875f, 30.0000f, 31, 31}, // 65b9 + {0.300293f, 0.400391f, 0.315430f, 0.415527f, -0.5000f, -28.6875f, 30.0000f, 31, 31}, // 65b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65bb - {0.687012f, 0.240234f, 0.702637f, 0.255371f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 65bc - {0.703125f, 0.240234f, 0.718750f, 0.255371f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 65bd + {0.920410f, 0.259766f, 0.936035f, 0.274902f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 65bc + {0.952148f, 0.259766f, 0.967773f, 0.274902f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 65bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c0 @@ -7207,17 +7508,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c4 - {0.748047f, 0.016113f, 0.764160f, 0.031738f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 65c5 + {0.423340f, 0.035645f, 0.439453f, 0.051270f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 65c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ca - {0.318848f, 0.082031f, 0.334473f, 0.097656f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 65cb + {0.224609f, 0.106445f, 0.240234f, 0.122070f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 65cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ce - {0.489258f, 0.082031f, 0.504883f, 0.097656f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 65cf + {0.240723f, 0.106445f, 0.256348f, 0.122070f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 65cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d2 @@ -7225,7 +7526,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d6 - {0.505371f, 0.082031f, 0.520996f, 0.097656f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 65d7 + {0.256836f, 0.106445f, 0.272461f, 0.122070f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 65d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65da @@ -7234,19 +7535,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65df - {0.356934f, 0.514648f, 0.372070f, 0.529297f, -0.0625f, -27.3750f, 30.0000f, 31, 30}, // 65e0 + {0.924805f, 0.540039f, 0.939941f, 0.554688f, -0.0625f, -27.3750f, 30.0000f, 31, 30}, // 65e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65e1 - {0.939453f, 0.430176f, 0.955078f, 0.444824f, -0.6250f, -27.5625f, 30.0000f, 32, 30}, // 65e2 + {0.140137f, 0.455566f, 0.155762f, 0.470215f, -0.6250f, -27.5625f, 30.0000f, 32, 30}, // 65e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65e4 - {0.499023f, 0.777344f, 0.509277f, 0.791016f, 5.1250f, -26.4375f, 30.0000f, 21, 28}, // 65e5 + {0.516602f, 0.848145f, 0.526855f, 0.861816f, 5.1250f, -26.4375f, 30.0000f, 21, 28}, // 65e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65e6 - {0.128418f, 0.708008f, 0.141113f, 0.722168f, 2.1875f, -27.3750f, 30.0000f, 26, 29}, // 65e7 - {0.451172f, 0.163086f, 0.463379f, 0.178223f, 3.8125f, -29.0625f, 30.0000f, 25, 31}, // 65e8 - {0.290039f, 0.585938f, 0.304688f, 0.600586f, 0.5625f, -27.3750f, 30.0000f, 30, 30}, // 65e9 + {0.863281f, 0.751465f, 0.875977f, 0.765625f, 2.1875f, -27.3750f, 30.0000f, 26, 29}, // 65e7 + {0.027344f, 0.735352f, 0.039551f, 0.750488f, 3.8125f, -29.0625f, 30.0000f, 25, 31}, // 65e8 + {0.600098f, 0.612793f, 0.614746f, 0.627441f, 0.5625f, -27.3750f, 30.0000f, 30, 30}, // 65e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65eb - {0.107422f, 0.515137f, 0.122070f, 0.530273f, -0.8750f, -29.1250f, 30.0000f, 30, 31}, // 65ec + {0.790527f, 0.540527f, 0.805176f, 0.555664f, -0.8750f, -29.1250f, 30.0000f, 30, 31}, // 65ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65ef @@ -7256,7 +7557,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f5 - {0.304199f, 0.615234f, 0.318359f, 0.630371f, 1.0625f, -28.8750f, 30.0000f, 29, 31}, // 65f6 + {0.640137f, 0.641602f, 0.654297f, 0.656738f, 1.0625f, -28.8750f, 30.0000f, 29, 31}, // 65f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 65f9 @@ -7272,21 +7573,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6603 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6604 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6605 - {0.000000f, 0.516113f, 0.015137f, 0.530762f, 0.4375f, -27.8750f, 30.0000f, 31, 30}, // 6606 - {0.234863f, 0.430664f, 0.250488f, 0.445313f, -0.5000f, -27.6875f, 30.0000f, 32, 30}, // 6607 + {0.964355f, 0.540527f, 0.979492f, 0.555176f, 0.4375f, -27.8750f, 30.0000f, 31, 30}, // 6606 + {0.203613f, 0.455566f, 0.219238f, 0.470215f, -0.5000f, -27.6875f, 30.0000f, 32, 30}, // 6607 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6608 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6609 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 660a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 660b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 660c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 660d - {0.296387f, 0.678711f, 0.309570f, 0.693359f, 1.2500f, -27.6250f, 30.0000f, 27, 30}, // 660e + {0.098145f, 0.719238f, 0.111328f, 0.733887f, 1.2500f, -27.6250f, 30.0000f, 27, 30}, // 660e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 660f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6610 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6611 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6612 - {0.953125f, 0.663086f, 0.966797f, 0.677734f, 0.1875f, -27.5000f, 30.0000f, 28, 30}, // 6613 - {0.015625f, 0.517578f, 0.030273f, 0.532715f, 0.3750f, -28.8750f, 30.0000f, 30, 31}, // 6614 + {0.762695f, 0.700195f, 0.776367f, 0.714844f, 0.1875f, -27.5000f, 30.0000f, 28, 30}, // 6613 + {0.940430f, 0.541016f, 0.955078f, 0.556152f, 0.3750f, -28.8750f, 30.0000f, 30, 31}, // 6614 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6615 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6616 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6617 @@ -7297,42 +7598,42 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 661c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 661d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 661e - {0.132813f, 0.663574f, 0.147461f, 0.677246f, 0.8750f, -27.3750f, 30.0000f, 30, 28}, // 661f - {0.250977f, 0.430664f, 0.265625f, 0.446289f, 0.6250f, -29.0000f, 30.0000f, 30, 32}, // 6620 + {0.188965f, 0.700684f, 0.203613f, 0.714355f, 0.8750f, -27.3750f, 30.0000f, 30, 28}, // 661f + {0.472168f, 0.455566f, 0.486816f, 0.471191f, 0.6250f, -29.0000f, 30.0000f, 30, 32}, // 6620 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6621 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6622 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6623 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6624 - {0.470703f, 0.082520f, 0.486328f, 0.098145f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 6625 + {0.552734f, 0.106445f, 0.568359f, 0.122070f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 6625 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6626 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6627 - {0.266113f, 0.430664f, 0.280762f, 0.446289f, 1.4375f, -29.3750f, 30.0000f, 30, 32}, // 6628 + {0.522949f, 0.455566f, 0.537598f, 0.471191f, 1.4375f, -29.3750f, 30.0000f, 30, 32}, // 6628 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6629 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 662a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 662b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 662c - {0.236328f, 0.663574f, 0.250000f, 0.678223f, 1.5625f, -27.5625f, 30.0000f, 28, 30}, // 662d + {0.268066f, 0.700684f, 0.281738f, 0.715332f, 1.5625f, -27.5625f, 30.0000f, 28, 30}, // 662d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 662e - {0.262207f, 0.518555f, 0.277344f, 0.533203f, 0.0000f, -27.7500f, 30.0000f, 31, 30}, // 662f + {0.264648f, 0.541504f, 0.279785f, 0.556152f, 0.0000f, -27.7500f, 30.0000f, 31, 30}, // 662f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6630 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6631 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6632 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6633 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6634 - {0.380859f, 0.585938f, 0.395508f, 0.600586f, 1.0625f, -27.3125f, 30.0000f, 30, 30}, // 6635 + {0.014648f, 0.613281f, 0.029297f, 0.627930f, 1.0625f, -27.3125f, 30.0000f, 30, 30}, // 6635 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6636 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6637 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6638 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6639 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 663a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 663b - {0.976563f, 0.555176f, 0.992188f, 0.569336f, -0.8125f, -27.6875f, 30.0000f, 32, 29}, // 663c + {0.416016f, 0.584961f, 0.431641f, 0.599121f, -0.8125f, -27.6875f, 30.0000f, 32, 29}, // 663c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 663d - {0.411133f, 0.615234f, 0.426270f, 0.629395f, -0.4375f, -27.5625f, 30.0000f, 31, 29}, // 663e + {0.119141f, 0.642090f, 0.134277f, 0.656250f, -0.4375f, -27.5625f, 30.0000f, 31, 29}, // 663e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 663f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6640 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6641 - {0.329590f, 0.430664f, 0.344238f, 0.446289f, 1.3750f, -29.1875f, 30.0000f, 30, 32}, // 6642 + {0.538086f, 0.455566f, 0.552734f, 0.471191f, 1.3750f, -29.1875f, 30.0000f, 30, 32}, // 6642 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6643 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6644 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6645 @@ -7371,20 +7672,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6666 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6667 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6668 - {0.735352f, 0.240234f, 0.750488f, 0.255859f, 0.9375f, -29.1875f, 30.0000f, 31, 32}, // 6669 + {0.826660f, 0.260254f, 0.841797f, 0.275879f, 0.9375f, -29.1875f, 30.0000f, 31, 32}, // 6669 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 666a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 666b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 666c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 666d - {0.770508f, 0.240234f, 0.785645f, 0.255859f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 666e - {0.046387f, 0.519043f, 0.061523f, 0.533691f, -0.2500f, -27.9375f, 30.0000f, 31, 30}, // 666f + {0.867676f, 0.260254f, 0.882813f, 0.275879f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 666e + {0.452637f, 0.541504f, 0.467773f, 0.556152f, -0.2500f, -27.9375f, 30.0000f, 31, 30}, // 666f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6670 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6671 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6672 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6673 - {0.062012f, 0.519043f, 0.076660f, 0.534180f, 0.2500f, -29.1875f, 30.0000f, 30, 31}, // 6674 + {0.894531f, 0.541992f, 0.909180f, 0.557129f, 0.2500f, -29.1875f, 30.0000f, 30, 31}, // 6674 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6675 - {0.299805f, 0.663574f, 0.313477f, 0.678223f, 1.5000f, -27.5625f, 30.0000f, 28, 30}, // 6676 + {0.056641f, 0.701172f, 0.070313f, 0.715820f, 1.5000f, -27.5625f, 30.0000f, 28, 30}, // 6676 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6677 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6678 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6679 @@ -7395,13 +7696,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 667e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 667f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6680 - {0.639648f, 0.381348f, 0.654785f, 0.396484f, 0.5625f, -28.5000f, 30.0000f, 31, 31}, // 6681 - {0.687012f, 0.381348f, 0.702148f, 0.396484f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 6682 + {0.932617f, 0.400391f, 0.947754f, 0.415527f, 0.5625f, -28.5000f, 30.0000f, 31, 31}, // 6681 + {0.948242f, 0.400391f, 0.963379f, 0.415527f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 6682 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6683 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6684 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6685 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6686 - {0.603516f, 0.585938f, 0.618164f, 0.600586f, 1.1875f, -27.7500f, 30.0000f, 30, 30}, // 6687 + {0.134766f, 0.613281f, 0.149414f, 0.627930f, 1.1875f, -27.7500f, 30.0000f, 30, 30}, // 6687 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6688 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6689 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 668a @@ -7411,13 +7712,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 668e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 668f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6690 - {0.822266f, 0.519043f, 0.837402f, 0.533691f, -0.1875f, -27.7500f, 30.0000f, 31, 30}, // 6691 + {0.388184f, 0.542480f, 0.403320f, 0.557129f, -0.1875f, -27.7500f, 30.0000f, 31, 30}, // 6691 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6692 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6693 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6694 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6695 - {0.344727f, 0.430664f, 0.359375f, 0.446289f, 0.6250f, -29.0625f, 30.0000f, 30, 32}, // 6696 - {0.617188f, 0.430664f, 0.631836f, 0.446289f, 0.9375f, -29.2500f, 30.0000f, 30, 32}, // 6697 + {0.569336f, 0.455566f, 0.583984f, 0.471191f, 0.6250f, -29.0625f, 30.0000f, 30, 32}, // 6696 + {0.651367f, 0.455566f, 0.666016f, 0.471191f, 0.9375f, -29.2500f, 30.0000f, 30, 32}, // 6697 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6698 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6699 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 669a @@ -7432,21 +7733,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a5 - {0.647949f, 0.430664f, 0.663574f, 0.445313f, -0.8750f, -27.8750f, 30.0000f, 32, 30}, // 66a6 + {0.078125f, 0.456055f, 0.093750f, 0.470703f, -0.8750f, -27.8750f, 30.0000f, 32, 30}, // 66a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66aa - {0.702148f, 0.430664f, 0.716797f, 0.446289f, 0.4375f, -29.0000f, 30.0000f, 30, 32}, // 66ab + {0.171875f, 0.456055f, 0.186523f, 0.471680f, 0.4375f, -29.0000f, 30.0000f, 30, 32}, // 66ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66ad - {0.727539f, 0.082520f, 0.743164f, 0.098145f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 66ae + {0.568848f, 0.106445f, 0.584473f, 0.122070f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 66ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b3 - {0.153320f, 0.519531f, 0.168457f, 0.534180f, -0.0625f, -27.6250f, 30.0000f, 31, 30}, // 66b4 + {0.805664f, 0.542480f, 0.820801f, 0.557129f, -0.0625f, -27.6250f, 30.0000f, 31, 30}, // 66b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66b7 @@ -7465,7 +7766,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66c6 - {0.719238f, 0.381348f, 0.734375f, 0.396484f, -0.3750f, -28.5625f, 30.0000f, 31, 31}, // 66c7 + {0.963867f, 0.400391f, 0.979004f, 0.415527f, -0.3750f, -28.5625f, 30.0000f, 31, 31}, // 66c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66ca @@ -7486,7 +7787,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66db - {0.532715f, 0.520020f, 0.547363f, 0.535156f, 0.5000f, -28.4375f, 30.0000f, 30, 31}, // 66dc + {0.846191f, 0.542969f, 0.860840f, 0.558105f, 0.5000f, -28.4375f, 30.0000f, 30, 31}, // 66dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66df @@ -7508,21 +7809,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f1 - {0.341309f, 0.693359f, 0.353516f, 0.708496f, 2.8750f, -28.9375f, 30.0000f, 25, 31}, // 66f2 + {0.068359f, 0.735352f, 0.080566f, 0.750488f, 2.8750f, -28.9375f, 30.0000f, 25, 31}, // 66f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f3 - {0.780762f, 0.430664f, 0.796387f, 0.445313f, -0.6250f, -27.3125f, 30.0000f, 32, 30}, // 66f4 + {0.187012f, 0.456055f, 0.202637f, 0.470703f, -0.6250f, -27.3125f, 30.0000f, 32, 30}, // 66f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66f7 - {0.875000f, 0.430664f, 0.889648f, 0.446289f, 0.5000f, -29.1250f, 30.0000f, 30, 32}, // 66f8 - {0.786133f, 0.240234f, 0.801270f, 0.255859f, -0.3750f, -28.9375f, 30.0000f, 31, 32}, // 66f9 + {0.553223f, 0.456055f, 0.567871f, 0.471680f, 0.5000f, -29.1250f, 30.0000f, 30, 32}, // 66f8 + {0.900879f, 0.260254f, 0.916016f, 0.275879f, -0.3750f, -28.9375f, 30.0000f, 31, 32}, // 66f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 66fe - {0.545898f, 0.240723f, 0.561035f, 0.256348f, -0.3750f, -29.0625f, 30.0000f, 31, 32}, // 66ff - {0.030762f, 0.520508f, 0.045898f, 0.535156f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 6700 + {0.936523f, 0.260742f, 0.951660f, 0.276367f, -0.3750f, -29.0625f, 30.0000f, 31, 32}, // 66ff + {0.322754f, 0.543457f, 0.337891f, 0.558105f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 6700 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6701 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6702 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6703 @@ -7530,12 +7831,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6705 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6706 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6707 - {0.928711f, 0.692871f, 0.941406f, 0.707520f, 0.5625f, -27.5000f, 30.0000f, 26, 30}, // 6708 - {0.850586f, 0.240723f, 0.865723f, 0.256348f, -0.6875f, -29.3125f, 30.0000f, 31, 32}, // 6709 + {0.095215f, 0.734375f, 0.107910f, 0.749023f, 0.5625f, -27.5000f, 30.0000f, 26, 30}, // 6708 + {0.968262f, 0.260742f, 0.983398f, 0.276367f, -0.6875f, -29.3125f, 30.0000f, 31, 32}, // 6709 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 670a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 670b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 670c - {0.672852f, 0.520996f, 0.687988f, 0.535645f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 670d + {0.369141f, 0.543457f, 0.384277f, 0.558105f, -0.4375f, -27.5000f, 30.0000f, 31, 30}, // 670d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 670e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 670f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6710 @@ -7543,17 +7844,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6712 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6713 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6714 - {0.521484f, 0.083496f, 0.537109f, 0.099121f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 6715 + {0.698730f, 0.106934f, 0.714355f, 0.122559f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 6715 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6716 - {0.890137f, 0.430664f, 0.904785f, 0.446289f, -0.5625f, -29.0000f, 30.0000f, 30, 32}, // 6717 + {0.584473f, 0.456055f, 0.599121f, 0.471680f, -0.5625f, -29.0000f, 30.0000f, 30, 32}, // 6717 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6718 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6719 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 671a - {0.649902f, 0.585938f, 0.664551f, 0.600586f, 0.1875f, -28.6875f, 30.0000f, 30, 30}, // 671b + {0.728516f, 0.613770f, 0.743164f, 0.628418f, 0.1875f, -28.6875f, 30.0000f, 30, 30}, // 671b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 671c - {0.710449f, 0.520508f, 0.725098f, 0.535645f, 0.1250f, -28.8750f, 30.0000f, 30, 31}, // 671d + {0.979980f, 0.543457f, 0.994629f, 0.558594f, 0.1250f, -28.8750f, 30.0000f, 30, 31}, // 671d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 671e - {0.218750f, 0.431152f, 0.233398f, 0.446777f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 671f + {0.109375f, 0.456543f, 0.124023f, 0.472168f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 671f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6720 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6721 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6722 @@ -7562,28 +7863,28 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6725 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6726 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6727 - {0.168945f, 0.521484f, 0.183594f, 0.536621f, 0.3125f, -28.8125f, 30.0000f, 30, 31}, // 6728 + {0.676758f, 0.543945f, 0.691406f, 0.559082f, 0.3125f, -28.8125f, 30.0000f, 30, 31}, // 6728 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6729 - {0.921875f, 0.240723f, 0.937012f, 0.256348f, -0.0625f, -29.1250f, 30.0000f, 31, 32}, // 672a - {0.221680f, 0.083984f, 0.237305f, 0.099609f, -0.3750f, -29.1875f, 30.0000f, 32, 32}, // 672b - {0.937500f, 0.240723f, 0.953125f, 0.255859f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 672c - {0.953613f, 0.240723f, 0.969238f, 0.255859f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 672d + {0.983887f, 0.260742f, 0.999023f, 0.276367f, -0.0625f, -29.1250f, 30.0000f, 31, 32}, // 672a + {0.737793f, 0.106934f, 0.753418f, 0.122559f, -0.3750f, -29.1875f, 30.0000f, 32, 32}, // 672b + {0.096191f, 0.262207f, 0.111816f, 0.277344f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 672c + {0.383789f, 0.263184f, 0.399414f, 0.278320f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 672d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 672e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 672f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6730 - {0.734863f, 0.381348f, 0.750000f, 0.396484f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 6731 + {0.979492f, 0.400391f, 0.994629f, 0.415527f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 6731 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6732 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6733 - {0.448242f, 0.241211f, 0.463867f, 0.256348f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 6734 + {0.626465f, 0.263184f, 0.642090f, 0.278320f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 6734 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6735 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6736 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6737 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6738 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6739 - {0.237793f, 0.083984f, 0.253418f, 0.099609f, -0.4375f, -28.8125f, 30.0000f, 32, 32}, // 673a + {0.753906f, 0.106934f, 0.769531f, 0.122559f, -0.4375f, -28.8125f, 30.0000f, 32, 32}, // 673a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 673b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 673c - {0.093750f, 0.381836f, 0.108887f, 0.396973f, -0.6875f, -29.0000f, 30.0000f, 31, 31}, // 673d + {0.847656f, 0.400879f, 0.862793f, 0.416016f, -0.6875f, -29.0000f, 30.0000f, 31, 31}, // 673d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 673e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 673f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6740 @@ -7592,18 +7893,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6743 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6744 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6745 - {0.497070f, 0.241211f, 0.512695f, 0.256348f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 6746 + {0.722656f, 0.263184f, 0.738281f, 0.278320f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 6746 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6747 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6748 - {0.253906f, 0.083984f, 0.269531f, 0.099609f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 6749 + {0.610840f, 0.107422f, 0.626465f, 0.123047f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 6749 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 674f - {0.719238f, 0.241211f, 0.734863f, 0.256348f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 6750 - {0.750977f, 0.241211f, 0.766602f, 0.256348f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 6751 + {0.399902f, 0.263672f, 0.415527f, 0.278809f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 6750 + {0.659180f, 0.263672f, 0.674805f, 0.278809f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 6751 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6752 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6753 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6754 @@ -7617,13 +7918,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 675c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 675d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 675e - {0.540039f, 0.381836f, 0.555176f, 0.396973f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 675f + {0.332031f, 0.401367f, 0.347168f, 0.416504f, 0.0625f, -29.0000f, 30.0000f, 31, 31}, // 675f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6760 - {0.801758f, 0.241211f, 0.817383f, 0.256348f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 6761 + {0.337891f, 0.264648f, 0.353516f, 0.279785f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 6761 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6762 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6763 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6764 - {0.834961f, 0.241211f, 0.850586f, 0.256348f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 6765 + {0.786621f, 0.265137f, 0.802246f, 0.280273f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 6765 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6766 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6767 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6768 @@ -7633,9 +7934,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 676c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 676d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 676e - {0.905762f, 0.241211f, 0.921387f, 0.256348f, -0.8125f, -29.0625f, 30.0000f, 32, 31}, // 676f + {0.802734f, 0.265137f, 0.818359f, 0.280273f, -0.8125f, -29.0625f, 30.0000f, 32, 31}, // 676f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6770 - {0.270020f, 0.083984f, 0.285645f, 0.099609f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 6771 + {0.626953f, 0.107422f, 0.642578f, 0.123047f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 6771 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6772 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6773 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6774 @@ -7648,8 +7949,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 677b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 677c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 677d - {0.969727f, 0.241211f, 0.985352f, 0.256348f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 677e - {0.049805f, 0.173828f, 0.065918f, 0.188965f, -1.1250f, -28.6875f, 30.0000f, 33, 31}, // 677f + {0.205566f, 0.266113f, 0.221191f, 0.281250f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 677e + {0.273926f, 0.192383f, 0.290039f, 0.207520f, -1.1250f, -28.6875f, 30.0000f, 33, 31}, // 677f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6780 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6781 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6782 @@ -7666,25 +7967,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 678d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 678e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 678f - {0.378906f, 0.085449f, 0.394531f, 0.101074f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6790 + {0.048340f, 0.107910f, 0.063965f, 0.123535f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6790 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6791 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6792 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6793 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6794 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6795 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6796 - {0.274414f, 0.241699f, 0.290039f, 0.256836f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 6797 + {0.514160f, 0.266113f, 0.529785f, 0.281250f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 6797 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6798 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6799 - {0.427734f, 0.088379f, 0.443359f, 0.104004f, -0.3125f, -29.3125f, 30.0000f, 32, 32}, // 679a + {0.064453f, 0.107910f, 0.080078f, 0.123535f, -0.3125f, -29.3125f, 30.0000f, 32, 32}, // 679a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 679b - {0.392090f, 0.432129f, 0.407715f, 0.446777f, -0.5625f, -27.6875f, 30.0000f, 32, 30}, // 679c - {0.290527f, 0.241699f, 0.306152f, 0.256836f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 679d + {0.062500f, 0.457520f, 0.078125f, 0.472168f, -0.5625f, -27.6875f, 30.0000f, 32, 30}, // 679c + {0.221680f, 0.266602f, 0.237305f, 0.281738f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 679d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 679e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 679f - {0.443848f, 0.088867f, 0.459473f, 0.104492f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 67a0 + {0.080566f, 0.107910f, 0.096191f, 0.123535f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 67a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67a1 - {0.464355f, 0.241699f, 0.479980f, 0.256836f, -1.1250f, -28.6875f, 30.0000f, 32, 31}, // 67a2 + {0.530273f, 0.266602f, 0.545898f, 0.281738f, -1.1250f, -28.6875f, 30.0000f, 32, 31}, // 67a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67a5 @@ -7697,14 +7998,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ae - {0.513184f, 0.241699f, 0.528809f, 0.256836f, -0.5000f, -29.1250f, 30.0000f, 32, 31}, // 67af + {0.642578f, 0.266602f, 0.658203f, 0.281738f, -0.5000f, -29.1250f, 30.0000f, 32, 31}, // 67af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b5 - {0.625977f, 0.241699f, 0.641602f, 0.256836f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 67b6 + {0.693848f, 0.266602f, 0.709473f, 0.281738f, -0.6250f, -28.8750f, 30.0000f, 32, 31}, // 67b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67b9 @@ -7718,7 +8019,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c3 - {0.670898f, 0.381836f, 0.686035f, 0.396973f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 67c4 + {0.397949f, 0.401367f, 0.413086f, 0.416504f, -0.6875f, -28.8750f, 30.0000f, 31, 31}, // 67c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67c7 @@ -7730,11 +8031,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67cf - {0.128906f, 0.090332f, 0.144531f, 0.105957f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 67d0 + {0.643066f, 0.108398f, 0.658691f, 0.124023f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 67d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67d2 - {0.145020f, 0.090332f, 0.160645f, 0.105957f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 67d3 - {0.547852f, 0.521484f, 0.562988f, 0.536133f, -0.5625f, -27.6250f, 30.0000f, 31, 30}, // 67d4 + {0.659180f, 0.108398f, 0.674805f, 0.124023f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 67d3 + {0.592285f, 0.544434f, 0.607422f, 0.559082f, -0.5625f, -27.6250f, 30.0000f, 31, 30}, // 67d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67d7 @@ -7751,7 +8052,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e4 - {0.442871f, 0.432129f, 0.458496f, 0.446777f, -0.5625f, -28.8125f, 30.0000f, 32, 30}, // 67e5 + {0.156250f, 0.458008f, 0.171875f, 0.472656f, -0.5625f, -28.8125f, 30.0000f, 32, 30}, // 67e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67e8 @@ -7763,9 +8064,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f0 - {0.334961f, 0.090820f, 0.350586f, 0.106445f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 67f1 + {0.145020f, 0.109375f, 0.160645f, 0.125000f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 67f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f2 - {0.798828f, 0.381836f, 0.813965f, 0.396973f, -1.0000f, -29.1250f, 30.0000f, 31, 31}, // 67f3 + {0.413574f, 0.401367f, 0.428711f, 0.416504f, -1.0000f, -29.1250f, 30.0000f, 31, 31}, // 67f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f6 @@ -7773,7 +8074,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67fa - {0.108398f, 0.437012f, 0.124023f, 0.451660f, -0.5000f, -28.8125f, 30.0000f, 32, 30}, // 67fb + {0.000000f, 0.458496f, 0.015625f, 0.473145f, -0.5000f, -28.8125f, 30.0000f, 32, 30}, // 67fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 67fe @@ -7782,10 +8083,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6801 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6802 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6803 - {0.863770f, 0.381836f, 0.878906f, 0.396973f, -0.1875f, -28.6250f, 30.0000f, 31, 31}, // 6804 + {0.522461f, 0.401367f, 0.537598f, 0.416504f, -0.1875f, -28.6250f, 30.0000f, 31, 31}, // 6804 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6805 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6806 - {0.258789f, 0.242188f, 0.274414f, 0.257324f, -1.3750f, -29.0000f, 30.0000f, 32, 31}, // 6807 + {0.562500f, 0.267090f, 0.578125f, 0.282227f, -1.3750f, -29.0000f, 30.0000f, 32, 31}, // 6807 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6808 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6809 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 680a @@ -7797,7 +8098,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6810 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6811 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6812 - {0.384277f, 0.242188f, 0.399902f, 0.257324f, -0.9375f, -28.8125f, 30.0000f, 32, 31}, // 6813 + {0.578613f, 0.267090f, 0.594238f, 0.282227f, -0.9375f, -28.8125f, 30.0000f, 32, 31}, // 6813 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6814 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6815 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6816 @@ -7811,7 +8112,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 681e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 681f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6820 - {0.658203f, 0.242188f, 0.673828f, 0.257324f, -0.9375f, -28.6875f, 30.0000f, 32, 31}, // 6821 + {0.675293f, 0.267090f, 0.690918f, 0.282227f, -0.9375f, -28.6875f, 30.0000f, 32, 31}, // 6821 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6822 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6823 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6824 @@ -7820,7 +8121,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6827 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6828 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6829 - {0.764648f, 0.016113f, 0.780762f, 0.031738f, -1.1875f, -29.1250f, 30.0000f, 33, 32}, // 682a + {0.477051f, 0.035645f, 0.493164f, 0.051270f, -1.1875f, -29.1250f, 30.0000f, 33, 32}, // 682a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 682b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 682c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 682d @@ -7833,24 +8134,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6834 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6835 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6836 - {0.432617f, 0.242676f, 0.448242f, 0.257813f, -1.5000f, -28.9375f, 30.0000f, 32, 31}, // 6837 - {0.480469f, 0.242676f, 0.496094f, 0.257813f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 6838 - {0.191895f, 0.243164f, 0.207520f, 0.258301f, -0.5000f, -28.6250f, 30.0000f, 32, 31}, // 6839 + {0.047852f, 0.267578f, 0.063477f, 0.282715f, -1.5000f, -28.9375f, 30.0000f, 32, 31}, // 6837 + {0.063965f, 0.268066f, 0.079590f, 0.283203f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 6838 + {0.080078f, 0.268066f, 0.095703f, 0.283203f, -0.5000f, -28.6250f, 30.0000f, 32, 31}, // 6839 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 683a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 683b - {0.238770f, 0.243652f, 0.254395f, 0.258789f, -0.6875f, -29.0625f, 30.0000f, 32, 31}, // 683c - {0.208008f, 0.244141f, 0.223633f, 0.259277f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 683d + {0.594727f, 0.268066f, 0.610352f, 0.283203f, -0.6875f, -29.0625f, 30.0000f, 32, 31}, // 683c + {0.610840f, 0.268066f, 0.626465f, 0.283203f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 683d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 683e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 683f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6840 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6841 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6842 - {0.351074f, 0.090820f, 0.366699f, 0.106445f, -0.8750f, -28.8750f, 30.0000f, 32, 32}, // 6843 + {0.177246f, 0.109375f, 0.192871f, 0.125000f, -0.8750f, -28.8750f, 30.0000f, 32, 32}, // 6843 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6844 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6845 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6846 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6847 - {0.000000f, 0.091797f, 0.015625f, 0.107422f, -0.1250f, -29.1875f, 30.0000f, 32, 32}, // 6848 + {0.193359f, 0.109375f, 0.208984f, 0.125000f, -0.1250f, -29.1875f, 30.0000f, 32, 32}, // 6848 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6849 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 684a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 684b @@ -7859,7 +8160,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 684e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 684f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6850 - {0.359863f, 0.437012f, 0.375488f, 0.451660f, -0.4375f, -27.6875f, 30.0000f, 32, 30}, // 6851 + {0.124512f, 0.458496f, 0.140137f, 0.473145f, -0.4375f, -27.6875f, 30.0000f, 32, 30}, // 6851 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6852 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6853 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6854 @@ -7870,14 +8171,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6859 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 685a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 685b - {0.337891f, 0.245605f, 0.353516f, 0.260742f, -0.3750f, -28.6250f, 30.0000f, 32, 31}, // 685c + {0.144043f, 0.268555f, 0.159668f, 0.283691f, -0.3750f, -28.6250f, 30.0000f, 32, 31}, // 685c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 685d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 685e - {0.400391f, 0.248535f, 0.416016f, 0.263672f, -1.3750f, -28.8125f, 30.0000f, 32, 31}, // 685f + {0.160156f, 0.268555f, 0.175781f, 0.283691f, -1.3750f, -28.8125f, 30.0000f, 32, 31}, // 685f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6860 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6861 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6862 - {0.125977f, 0.382324f, 0.141113f, 0.397461f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 6863 + {0.880371f, 0.401367f, 0.895508f, 0.416504f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 6863 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6864 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6865 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6866 @@ -7905,13 +8206,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 687c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 687d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 687e - {0.507324f, 0.382324f, 0.522461f, 0.397461f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 687f + {0.915039f, 0.401367f, 0.930176f, 0.416504f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 687f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6880 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6881 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6882 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6883 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6884 - {0.016113f, 0.091797f, 0.031738f, 0.107422f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 6885 + {0.161133f, 0.109863f, 0.176758f, 0.125488f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 6885 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6886 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6887 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6888 @@ -7935,7 +8236,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 689a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 689b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 689c - {0.781250f, 0.016113f, 0.797363f, 0.031738f, -0.7500f, -29.1875f, 30.0000f, 33, 32}, // 689d + {0.493652f, 0.035645f, 0.509766f, 0.051270f, -0.7500f, -29.1875f, 30.0000f, 33, 32}, // 689d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 689e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 689f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68a0 @@ -7954,7 +8255,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68af - {0.032227f, 0.091797f, 0.047852f, 0.107422f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 68b0 + {0.000000f, 0.110840f, 0.015625f, 0.126465f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 68b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68b3 @@ -7970,25 +8271,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68bf - {0.112305f, 0.249023f, 0.127930f, 0.264160f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 68c0 + {0.112305f, 0.269043f, 0.127930f, 0.284180f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 68c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c3 - {0.048340f, 0.093262f, 0.063965f, 0.108887f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 68c4 + {0.016113f, 0.110840f, 0.031738f, 0.126465f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 68c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ca - {0.416504f, 0.249023f, 0.432129f, 0.264160f, -1.1875f, -28.8750f, 30.0000f, 32, 31}, // 68cb + {0.128418f, 0.269043f, 0.144043f, 0.284180f, -1.1875f, -28.8750f, 30.0000f, 32, 31}, // 68cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d1 - {0.797852f, 0.016113f, 0.813965f, 0.031738f, -1.2500f, -29.1250f, 30.0000f, 33, 32}, // 68d2 + {0.510254f, 0.035645f, 0.526367f, 0.051270f, -1.2500f, -29.1250f, 30.0000f, 33, 32}, // 68d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d5 @@ -7996,12 +8297,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68d9 - {0.563477f, 0.521484f, 0.578125f, 0.536621f, -0.3125f, -28.6250f, 30.0000f, 30, 31}, // 68da + {0.861328f, 0.544434f, 0.875977f, 0.559570f, -0.3125f, -28.6250f, 30.0000f, 30, 31}, // 68da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68de - {0.306641f, 0.249512f, 0.322266f, 0.264648f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 68df + {0.176270f, 0.269043f, 0.191895f, 0.284180f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 68df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68e2 @@ -8016,7 +8317,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ed - {0.814453f, 0.016113f, 0.830566f, 0.031738f, -1.1250f, -29.0000f, 30.0000f, 33, 32}, // 68ee + {0.526855f, 0.035645f, 0.542969f, 0.051270f, -1.1250f, -29.0000f, 30.0000f, 33, 32}, // 68ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68f1 @@ -8028,7 +8329,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68f9 - {0.522949f, 0.382324f, 0.538086f, 0.397461f, -0.8125f, -28.8750f, 30.0000f, 31, 31}, // 68fa + {0.381348f, 0.401855f, 0.396484f, 0.416992f, -0.8125f, -28.8750f, 30.0000f, 31, 31}, // 68fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 68fd @@ -8047,7 +8348,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 690a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 690b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 690c - {0.064453f, 0.093262f, 0.080078f, 0.108887f, -1.1875f, -29.0625f, 30.0000f, 32, 32}, // 690d + {0.032227f, 0.110840f, 0.047852f, 0.126465f, -1.1875f, -29.0625f, 30.0000f, 32, 32}, // 690d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 690e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 690f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6910 @@ -8062,7 +8363,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6919 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 691a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 691b - {0.000000f, 0.250488f, 0.015625f, 0.265625f, -1.0000f, -29.1250f, 30.0000f, 32, 31}, // 691c + {0.016113f, 0.269531f, 0.031738f, 0.284668f, -1.0000f, -29.1250f, 30.0000f, 32, 31}, // 691c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 691d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 691e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 691f @@ -8143,7 +8444,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 696a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 696b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 696c - {0.080566f, 0.093262f, 0.096191f, 0.108887f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 696d + {0.792480f, 0.111328f, 0.808105f, 0.126953f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 696d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 696e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 696f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6970 @@ -8151,20 +8452,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6972 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6973 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6974 - {0.016113f, 0.251465f, 0.031738f, 0.266602f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 6975 + {0.000000f, 0.270508f, 0.015625f, 0.285645f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 6975 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6976 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6977 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6978 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6979 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 697a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 697b - {0.064453f, 0.251953f, 0.080078f, 0.267090f, -1.5000f, -29.1875f, 30.0000f, 32, 31}, // 697c - {0.096680f, 0.093262f, 0.112305f, 0.108887f, -0.5625f, -29.4375f, 30.0000f, 32, 32}, // 697d + {0.738770f, 0.270508f, 0.754395f, 0.285645f, -1.5000f, -29.1875f, 30.0000f, 32, 31}, // 697c + {0.808594f, 0.111328f, 0.824219f, 0.126953f, -0.5625f, -29.4375f, 30.0000f, 32, 32}, // 697d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 697e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 697f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6980 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6981 - {0.066406f, 0.173828f, 0.082520f, 0.188965f, -1.1250f, -28.7500f, 30.0000f, 33, 31}, // 6982 + {0.290527f, 0.192383f, 0.306641f, 0.207520f, -1.1250f, -28.7500f, 30.0000f, 33, 31}, // 6982 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6983 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6984 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6985 @@ -8237,7 +8538,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69ca - {0.032227f, 0.252441f, 0.047852f, 0.267578f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 69cb + {0.754883f, 0.270508f, 0.770508f, 0.285645f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 69cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69ce @@ -8250,7 +8551,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69d7 - {0.831055f, 0.016113f, 0.847168f, 0.031738f, -1.0000f, -29.3125f, 30.0000f, 33, 32}, // 69d8 + {0.971191f, 0.035645f, 0.987305f, 0.051270f, -1.0000f, -29.3125f, 30.0000f, 33, 32}, // 69d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69db @@ -8287,12 +8588,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69fc - {0.048340f, 0.252441f, 0.063965f, 0.267578f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 69fd + {0.253906f, 0.270996f, 0.269531f, 0.286133f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 69fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 69ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a01 - {0.112793f, 0.095215f, 0.128418f, 0.110840f, -0.2500f, -29.4375f, 30.0000f, 32, 32}, // 6a02 + {0.296387f, 0.111816f, 0.312012f, 0.127441f, -0.2500f, -29.4375f, 30.0000f, 32, 32}, // 6a02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a05 @@ -8315,7 +8616,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a18 - {0.080566f, 0.252441f, 0.096191f, 0.267578f, -1.0625f, -28.5625f, 30.0000f, 32, 31}, // 6a19 + {0.237793f, 0.271484f, 0.253418f, 0.286621f, -1.0625f, -28.5625f, 30.0000f, 32, 31}, // 6a19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a1c @@ -8323,16 +8624,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a20 - {0.160156f, 0.254883f, 0.175781f, 0.270020f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 6a21 + {0.270020f, 0.271484f, 0.285645f, 0.286621f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 6a21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a22 - {0.847656f, 0.016113f, 0.863770f, 0.031738f, -1.0000f, -29.5000f, 30.0000f, 33, 32}, // 6a23 + {0.910645f, 0.036133f, 0.926758f, 0.051758f, -1.0000f, -29.5000f, 30.0000f, 33, 32}, // 6a23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a28 - {0.864258f, 0.016113f, 0.880371f, 0.031738f, -1.3125f, -29.0000f, 30.0000f, 33, 32}, // 6a29 - {0.354004f, 0.254883f, 0.369629f, 0.270020f, -1.2500f, -28.6875f, 30.0000f, 32, 31}, // 6a2a + {0.951660f, 0.036621f, 0.967773f, 0.052246f, -1.3125f, -29.0000f, 30.0000f, 33, 32}, // 6a29 + {0.286133f, 0.271484f, 0.301758f, 0.286621f, -1.2500f, -28.6875f, 30.0000f, 32, 31}, // 6a2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a2d @@ -8347,7 +8648,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a38 - {0.642090f, 0.254883f, 0.657715f, 0.270020f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 6a39 + {0.302246f, 0.271484f, 0.317871f, 0.286621f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 6a39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a3c @@ -8365,7 +8666,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a4a - {0.096680f, 0.255371f, 0.112305f, 0.270508f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 6a4b + {0.032227f, 0.272461f, 0.047852f, 0.287598f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 6a4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a4e @@ -8385,7 +8686,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a5e - {0.128418f, 0.255371f, 0.144043f, 0.270508f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 6a5f + {0.464355f, 0.272461f, 0.479980f, 0.287598f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 6a5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a62 @@ -8438,7 +8739,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a93 - {0.607910f, 0.382324f, 0.623047f, 0.397461f, -0.6250f, -29.1875f, 30.0000f, 31, 31}, // 6a94 + {0.863281f, 0.402832f, 0.878418f, 0.417969f, -0.6250f, -29.1875f, 30.0000f, 31, 31}, // 6a94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a97 @@ -8452,7 +8753,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6a9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6aa0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6aa1 - {0.896973f, 0.016113f, 0.913086f, 0.031738f, -1.0000f, -29.7500f, 30.0000f, 33, 32}, // 6aa2 + {0.802734f, 0.038086f, 0.818848f, 0.053711f, -1.0000f, -29.7500f, 30.0000f, 33, 32}, // 6aa2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6aa3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6aa4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6aa5 @@ -8550,7 +8851,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b03 - {0.322754f, 0.252930f, 0.337891f, 0.268555f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 6b04 + {0.496582f, 0.272461f, 0.511719f, 0.288086f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 6b04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b07 @@ -8578,14 +8879,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b1f - {0.161133f, 0.095703f, 0.176758f, 0.111328f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 6b20 - {0.176270f, 0.255371f, 0.191895f, 0.270508f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 6b21 + {0.312500f, 0.111816f, 0.328125f, 0.127441f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 6b20 + {0.480469f, 0.272949f, 0.496094f, 0.288086f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 6b21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b26 - {0.578613f, 0.521484f, 0.593262f, 0.536621f, 1.0000f, -29.0000f, 30.0000f, 30, 31}, // 6b27 + {0.876465f, 0.544922f, 0.891113f, 0.560059f, 1.0000f, -29.0000f, 30.0000f, 30, 31}, // 6b27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b2a @@ -8596,7 +8897,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b31 - {0.193359f, 0.095703f, 0.208984f, 0.111328f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 6b32 + {0.328613f, 0.111816f, 0.344238f, 0.127441f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 6b32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b35 @@ -8604,11 +8905,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b39 - {0.561523f, 0.255371f, 0.577148f, 0.270508f, -0.1875f, -29.0000f, 30.0000f, 32, 31}, // 6b3a + {0.770996f, 0.272949f, 0.786621f, 0.288086f, -0.1875f, -29.0000f, 30.0000f, 32, 31}, // 6b3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b3d - {0.395020f, 0.095703f, 0.410645f, 0.111328f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 6b3e + {0.344727f, 0.111816f, 0.360352f, 0.127441f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 6b3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b41 @@ -8619,17 +8920,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b48 - {0.913574f, 0.016113f, 0.929688f, 0.031738f, -1.0000f, -29.2500f, 30.0000f, 33, 32}, // 6b49 + {0.439941f, 0.038574f, 0.456055f, 0.054199f, -1.0000f, -29.2500f, 30.0000f, 33, 32}, // 6b49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b4b - {0.817871f, 0.255371f, 0.833008f, 0.270996f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 6b4c + {0.318359f, 0.273438f, 0.333496f, 0.289063f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 6b4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b52 - {0.411133f, 0.095703f, 0.426758f, 0.111328f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 6b53 + {0.360840f, 0.111816f, 0.376465f, 0.127441f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 6b53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b56 @@ -8644,32 +8945,32 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b61 - {0.703125f, 0.663574f, 0.717773f, 0.677246f, 0.2500f, -27.8125f, 30.0000f, 30, 28}, // 6b62 - {0.677246f, 0.691406f, 0.691406f, 0.704590f, 1.0000f, -26.6875f, 30.0000f, 29, 27}, // 6b63 - {0.375977f, 0.437500f, 0.391602f, 0.452148f, -0.9375f, -28.1875f, 30.0000f, 32, 30}, // 6b64 - {0.927246f, 0.382324f, 0.942383f, 0.397461f, -0.3125f, -29.0625f, 30.0000f, 31, 31}, // 6b65 - {0.972656f, 0.382324f, 0.987793f, 0.397461f, -0.1250f, -29.0625f, 30.0000f, 31, 31}, // 6b66 + {0.601563f, 0.701172f, 0.616211f, 0.714844f, 0.2500f, -27.8125f, 30.0000f, 30, 28}, // 6b62 + {0.732422f, 0.731445f, 0.746582f, 0.744629f, 1.0000f, -26.6875f, 30.0000f, 29, 27}, // 6b63 + {0.251953f, 0.458984f, 0.267578f, 0.473633f, -0.9375f, -28.1875f, 30.0000f, 32, 30}, // 6b64 + {0.832520f, 0.403320f, 0.847656f, 0.418457f, -0.3125f, -29.0625f, 30.0000f, 31, 31}, // 6b65 + {0.095215f, 0.403809f, 0.110352f, 0.418945f, -0.1250f, -29.0625f, 30.0000f, 31, 31}, // 6b66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b68 - {0.866211f, 0.255371f, 0.881836f, 0.270508f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 6b69 + {0.842285f, 0.273926f, 0.857910f, 0.289063f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 6b69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b6e - {0.203613f, 0.432129f, 0.218262f, 0.447754f, 0.9375f, -29.0625f, 30.0000f, 30, 32}, // 6b6f + {0.710938f, 0.458984f, 0.725586f, 0.474609f, 0.9375f, -29.0625f, 30.0000f, 30, 32}, // 6b6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b72 - {0.144531f, 0.255859f, 0.159668f, 0.271484f, -0.5625f, -29.0625f, 30.0000f, 31, 32}, // 6b73 - {0.000000f, 0.437988f, 0.015625f, 0.452637f, -1.0000f, -28.0000f, 30.0000f, 32, 30}, // 6b74 + {0.883301f, 0.274902f, 0.898438f, 0.290527f, -0.5625f, -29.0625f, 30.0000f, 31, 32}, // 6b73 + {0.268066f, 0.459473f, 0.283691f, 0.474121f, -1.0000f, -28.0000f, 30.0000f, 32, 30}, // 6b74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b7a - {0.504883f, 0.615234f, 0.520020f, 0.629395f, -0.1875f, -26.8750f, 30.0000f, 31, 29}, // 6b7b + {0.501465f, 0.642090f, 0.516602f, 0.656250f, -0.1875f, -26.8750f, 30.0000f, 31, 29}, // 6b7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b7e @@ -8683,9 +8984,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b88 - {0.299316f, 0.434570f, 0.313965f, 0.450195f, -0.1250f, -29.0625f, 30.0000f, 30, 32}, // 6b89 - {0.529297f, 0.255859f, 0.544922f, 0.270996f, -0.1875f, -29.0000f, 30.0000f, 32, 31}, // 6b8a - {0.698242f, 0.095703f, 0.713867f, 0.111328f, -0.6250f, -29.3750f, 30.0000f, 32, 32}, // 6b8b + {0.726074f, 0.459473f, 0.740723f, 0.475098f, -0.1250f, -29.0625f, 30.0000f, 30, 32}, // 6b89 + {0.354004f, 0.275391f, 0.369629f, 0.290527f, -0.1875f, -29.0000f, 30.0000f, 32, 31}, // 6b8a + {0.272949f, 0.112305f, 0.288574f, 0.127930f, -0.6250f, -29.3750f, 30.0000f, 32, 32}, // 6b8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b8e @@ -8696,7 +8997,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b95 - {0.177246f, 0.096191f, 0.192871f, 0.111816f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 6b96 + {0.518066f, 0.113281f, 0.533691f, 0.128906f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 6b96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6b99 @@ -8726,18 +9027,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb3 - {0.841309f, 0.585938f, 0.855957f, 0.600586f, 0.9375f, -27.8125f, 30.0000f, 30, 30}, // 6bb4 - {0.571777f, 0.096680f, 0.587402f, 0.112305f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6bb5 + {0.227539f, 0.614258f, 0.242188f, 0.628906f, 0.9375f, -27.8125f, 30.0000f, 30, 30}, // 6bb4 + {0.534180f, 0.113281f, 0.549805f, 0.128906f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 6bb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bb9 - {0.593750f, 0.255859f, 0.609375f, 0.270996f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 6bba - {0.587891f, 0.096680f, 0.603516f, 0.112305f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6bbb + {0.416016f, 0.275391f, 0.431641f, 0.290527f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 6bba + {0.824707f, 0.113281f, 0.840332f, 0.128906f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6bbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bbe - {0.083008f, 0.173828f, 0.099121f, 0.188965f, -1.1250f, -28.0000f, 30.0000f, 33, 31}, // 6bbf + {0.307129f, 0.192383f, 0.323242f, 0.207520f, -1.1250f, -28.0000f, 30.0000f, 33, 31}, // 6bbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bc2 @@ -8751,21 +9052,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bcb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bcc - {0.974121f, 0.585938f, 0.988770f, 0.600586f, 0.3125f, -27.5000f, 30.0000f, 30, 30}, // 6bcd - {0.609863f, 0.255859f, 0.625000f, 0.271484f, -0.1250f, -29.3125f, 30.0000f, 31, 32}, // 6bce - {0.674316f, 0.255859f, 0.689453f, 0.271484f, -0.0625f, -29.3125f, 30.0000f, 31, 32}, // 6bcf + {0.379883f, 0.615234f, 0.394531f, 0.629883f, 0.3125f, -27.5000f, 30.0000f, 30, 30}, // 6bcd + {0.448242f, 0.275391f, 0.463379f, 0.291016f, -0.1250f, -29.3125f, 30.0000f, 31, 32}, // 6bce + {0.546387f, 0.275391f, 0.561523f, 0.291016f, -0.0625f, -29.3125f, 30.0000f, 31, 32}, // 6bcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd1 - {0.689941f, 0.255859f, 0.705078f, 0.271484f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 6bd2 + {0.916504f, 0.275391f, 0.931641f, 0.291016f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 6bd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd3 - {0.483887f, 0.521973f, 0.499023f, 0.536621f, -0.2500f, -28.3750f, 30.0000f, 31, 30}, // 6bd4 + {0.338379f, 0.545898f, 0.353516f, 0.560547f, -0.2500f, -28.3750f, 30.0000f, 31, 30}, // 6bd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bda - {0.074219f, 0.586426f, 0.088867f, 0.601074f, 0.3125f, -28.6875f, 30.0000f, 30, 30}, // 6bdb + {0.395020f, 0.615234f, 0.409668f, 0.629883f, 0.3125f, -28.6875f, 30.0000f, 30, 30}, // 6bdb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bdc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6bde @@ -8817,15 +9118,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c0e - {0.756348f, 0.521484f, 0.770996f, 0.536621f, 0.4375f, -28.8750f, 30.0000f, 30, 31}, // 6c0f + {0.091797f, 0.546875f, 0.106445f, 0.562012f, 0.4375f, -28.8750f, 30.0000f, 30, 31}, // 6c0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c10 - {0.047363f, 0.439941f, 0.062988f, 0.454590f, -0.5000f, -27.5625f, 30.0000f, 32, 30}, // 6c11 + {0.219727f, 0.459961f, 0.235352f, 0.474609f, -0.5000f, -27.5625f, 30.0000f, 32, 30}, // 6c11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c16 - {0.604004f, 0.096680f, 0.619629f, 0.112305f, -0.9375f, -29.6250f, 30.0000f, 32, 32}, // 6c17 + {0.899902f, 0.114746f, 0.915527f, 0.130371f, -0.9375f, -29.6250f, 30.0000f, 32, 32}, // 6c17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c1a @@ -8854,11 +9155,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c33 - {0.882324f, 0.255859f, 0.897949f, 0.270996f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c34 + {0.952148f, 0.275391f, 0.967773f, 0.290527f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c36 - {0.577637f, 0.256348f, 0.593262f, 0.271484f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c37 - {0.620117f, 0.096680f, 0.635742f, 0.112305f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 6c38 + {0.432129f, 0.275879f, 0.447754f, 0.291016f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c37 + {0.403320f, 0.116211f, 0.418945f, 0.131836f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 6c38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c3b @@ -8867,15 +9168,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c40 - {0.735352f, 0.256348f, 0.750977f, 0.271484f, -0.2500f, -29.0000f, 30.0000f, 32, 31}, // 6c41 - {0.767090f, 0.256348f, 0.782227f, 0.271973f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 6c42 + {0.818848f, 0.276367f, 0.834473f, 0.291504f, -0.2500f, -29.0000f, 30.0000f, 32, 31}, // 6c41 + {0.858398f, 0.276367f, 0.873535f, 0.291992f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 6c42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c46 - {0.641602f, 0.521973f, 0.656738f, 0.536621f, -0.6875f, -28.1250f, 30.0000f, 31, 30}, // 6c47 + {0.106934f, 0.546875f, 0.122070f, 0.561523f, -0.6875f, -28.1250f, 30.0000f, 31, 30}, // 6c47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c48 - {0.016113f, 0.440918f, 0.031738f, 0.455566f, -0.8125f, -28.1250f, 30.0000f, 32, 30}, // 6c49 + {0.235840f, 0.460449f, 0.251465f, 0.475098f, -0.8125f, -28.1250f, 30.0000f, 32, 30}, // 6c49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c4c @@ -8889,16 +9190,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c56 - {0.281250f, 0.441895f, 0.296875f, 0.456543f, -0.6250f, -27.9375f, 30.0000f, 32, 30}, // 6c57 + {0.016113f, 0.460938f, 0.031738f, 0.475586f, -0.6250f, -27.9375f, 30.0000f, 32, 30}, // 6c57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c59 - {0.827637f, 0.441895f, 0.843262f, 0.456543f, -0.5625f, -28.0625f, 30.0000f, 32, 30}, // 6c5a + {0.423828f, 0.460938f, 0.439453f, 0.475586f, -0.5625f, -28.0625f, 30.0000f, 32, 30}, // 6c5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c5e - {0.420898f, 0.522461f, 0.436035f, 0.537109f, -0.0625f, -27.9375f, 30.0000f, 31, 30}, // 6c5f - {0.782715f, 0.256348f, 0.798340f, 0.271484f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c60 + {0.622559f, 0.546875f, 0.637695f, 0.561523f, -0.0625f, -27.9375f, 30.0000f, 31, 30}, // 6c5f + {0.898926f, 0.276367f, 0.914551f, 0.291504f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6c60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c63 @@ -8924,10 +9225,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c79 - {0.636230f, 0.096680f, 0.651855f, 0.112305f, -0.3125f, -29.1250f, 30.0000f, 32, 32}, // 6c7a + {0.452148f, 0.116211f, 0.467773f, 0.131836f, -0.3125f, -29.1250f, 30.0000f, 32, 32}, // 6c7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c7c - {0.937500f, 0.256348f, 0.952637f, 0.271973f, -0.1250f, -29.5625f, 30.0000f, 31, 32}, // 6c7d + {0.932129f, 0.276855f, 0.947266f, 0.292480f, -0.1250f, -29.5625f, 30.0000f, 31, 32}, // 6c7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c80 @@ -8938,7 +9239,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c87 - {0.141602f, 0.382813f, 0.156738f, 0.397949f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 6c88 + {0.895996f, 0.403809f, 0.911133f, 0.418945f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 6c88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c8b @@ -8948,11 +9249,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c91 - {0.953125f, 0.256348f, 0.968262f, 0.271973f, -0.3125f, -29.2500f, 30.0000f, 31, 32}, // 6c92 + {0.968262f, 0.276855f, 0.983398f, 0.292480f, -0.3125f, -29.2500f, 30.0000f, 31, 32}, // 6c92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c95 - {0.063477f, 0.441406f, 0.078125f, 0.457031f, -0.3750f, -29.1875f, 30.0000f, 30, 32}, // 6c96 + {0.439941f, 0.460938f, 0.454590f, 0.476563f, -0.3750f, -29.1875f, 30.0000f, 30, 32}, // 6c96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c99 @@ -8963,8 +9264,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6c9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ca0 - {0.448730f, 0.256836f, 0.464355f, 0.271973f, -0.6250f, -28.1875f, 30.0000f, 32, 31}, // 6ca1 - {0.099609f, 0.175781f, 0.115723f, 0.190918f, -0.8125f, -28.1875f, 30.0000f, 33, 31}, // 6ca2 + {0.983887f, 0.276855f, 0.999512f, 0.291992f, -0.6250f, -28.1875f, 30.0000f, 32, 31}, // 6ca1 + {0.323730f, 0.192383f, 0.339844f, 0.207520f, -0.8125f, -28.1875f, 30.0000f, 33, 31}, // 6ca2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ca3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ca4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ca5 @@ -8981,21 +9282,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb2 - {0.155273f, 0.442871f, 0.170898f, 0.457520f, -0.5625f, -27.8750f, 30.0000f, 32, 30}, // 6cb3 + {0.741211f, 0.460938f, 0.756836f, 0.475586f, -0.5625f, -27.8750f, 30.0000f, 32, 30}, // 6cb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cb7 - {0.415039f, 0.382813f, 0.430176f, 0.397949f, -0.7500f, -28.7500f, 30.0000f, 31, 31}, // 6cb8 - {0.032227f, 0.441895f, 0.046875f, 0.457520f, -0.1250f, -29.1250f, 30.0000f, 30, 32}, // 6cb9 + {0.347656f, 0.404297f, 0.362793f, 0.419434f, -0.7500f, -28.7500f, 30.0000f, 31, 31}, // 6cb8 + {0.455078f, 0.462402f, 0.469727f, 0.478027f, -0.1250f, -29.1250f, 30.0000f, 30, 32}, // 6cb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cba - {0.496582f, 0.256836f, 0.512207f, 0.271973f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6cbb - {0.609863f, 0.522461f, 0.624512f, 0.537598f, -0.5000f, -28.5625f, 30.0000f, 30, 31}, // 6cbc + {0.096191f, 0.277832f, 0.111816f, 0.292969f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6cbb + {0.755859f, 0.546875f, 0.770508f, 0.562012f, -0.5000f, -28.5625f, 30.0000f, 30, 31}, // 6cbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cbe - {0.801270f, 0.522461f, 0.816406f, 0.537109f, -0.7500f, -28.4375f, 30.0000f, 31, 30}, // 6cbf + {0.770996f, 0.546875f, 0.786133f, 0.561523f, -0.7500f, -28.4375f, 30.0000f, 31, 30}, // 6cbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc0 - {0.545410f, 0.256836f, 0.561035f, 0.271973f, -0.3125f, -28.3750f, 30.0000f, 32, 31}, // 6cc1 + {0.370117f, 0.278809f, 0.385742f, 0.293945f, -0.3125f, -28.3750f, 30.0000f, 32, 31}, // 6cc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc4 @@ -9003,10 +9304,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cc8 - {0.652344f, 0.096680f, 0.667969f, 0.112305f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 6cc9 - {0.449219f, 0.555664f, 0.463379f, 0.571289f, -0.2500f, -29.4375f, 30.0000f, 29, 32}, // 6cca + {0.468262f, 0.116211f, 0.483887f, 0.131836f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 6cc9 + {0.684570f, 0.584961f, 0.698730f, 0.600586f, -0.2500f, -29.4375f, 30.0000f, 29, 32}, // 6cca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ccb - {0.538574f, 0.442871f, 0.554199f, 0.457520f, -0.7500f, -28.9375f, 30.0000f, 32, 30}, // 6ccc + {0.506348f, 0.462891f, 0.521973f, 0.477539f, -0.7500f, -28.9375f, 30.0000f, 32, 30}, // 6ccc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ccd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ccf @@ -9015,7 +9316,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd4 - {0.575684f, 0.382813f, 0.590820f, 0.397949f, -0.1250f, -28.6250f, 30.0000f, 31, 31}, // 6cd5 + {0.617188f, 0.404785f, 0.632324f, 0.419922f, -0.1250f, -28.6250f, 30.0000f, 31, 31}, // 6cd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cd8 @@ -9027,14 +9328,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cdf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ce0 - {0.705566f, 0.256836f, 0.721191f, 0.271973f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6ce1 - {0.743652f, 0.096680f, 0.759277f, 0.112305f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 6ce2 - {0.837891f, 0.522461f, 0.853027f, 0.537109f, -0.1875f, -28.6250f, 30.0000f, 31, 30}, // 6ce3 + {0.626953f, 0.278809f, 0.642578f, 0.293945f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 6ce1 + {0.484375f, 0.116211f, 0.500000f, 0.131836f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 6ce2 + {0.280273f, 0.547363f, 0.295410f, 0.562012f, -0.1875f, -28.6250f, 30.0000f, 31, 30}, // 6ce3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ce4 - {0.751465f, 0.256836f, 0.767090f, 0.271973f, -0.3125f, -28.6875f, 30.0000f, 32, 31}, // 6ce5 + {0.709961f, 0.278809f, 0.725586f, 0.293945f, -0.3125f, -28.6875f, 30.0000f, 32, 31}, // 6ce5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ce6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ce7 - {0.750488f, 0.382813f, 0.765625f, 0.397949f, -0.1875f, -29.1875f, 30.0000f, 31, 31}, // 6ce8 + {0.363281f, 0.405273f, 0.378418f, 0.420410f, -0.1875f, -29.1875f, 30.0000f, 31, 31}, // 6ce8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ce9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ceb @@ -9042,10 +9343,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ced {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cef - {0.759766f, 0.096680f, 0.775391f, 0.112305f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 6cf0 + {0.500488f, 0.116211f, 0.516113f, 0.131836f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 6cf0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cf2 - {0.930176f, 0.016113f, 0.946289f, 0.031738f, -0.7500f, -29.5625f, 30.0000f, 33, 32}, // 6cf3 + {0.456543f, 0.038574f, 0.472656f, 0.054199f, -0.7500f, -29.5625f, 30.0000f, 33, 32}, // 6cf3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cf4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6cf6 @@ -9069,7 +9370,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d0a - {0.775879f, 0.096680f, 0.791504f, 0.112305f, -0.7500f, -29.4375f, 30.0000f, 32, 32}, // 6d0b + {0.584961f, 0.116211f, 0.600586f, 0.131836f, -0.7500f, -29.4375f, 30.0000f, 32, 32}, // 6d0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d0e @@ -9081,26 +9382,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d16 - {0.798828f, 0.256836f, 0.814453f, 0.271973f, -0.2500f, -29.0000f, 30.0000f, 32, 31}, // 6d17 + {0.386230f, 0.279297f, 0.401855f, 0.294434f, -0.2500f, -29.0000f, 30.0000f, 32, 31}, // 6d17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d1d - {0.901855f, 0.522461f, 0.916504f, 0.537598f, -0.5625f, -28.6250f, 30.0000f, 30, 31}, // 6d1e + {0.295898f, 0.547363f, 0.310547f, 0.562500f, -0.5625f, -28.6250f, 30.0000f, 30, 31}, // 6d1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d24 - {0.791992f, 0.096680f, 0.807617f, 0.112305f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 6d25 + {0.935547f, 0.116211f, 0.951172f, 0.131836f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 6d25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d29 - {0.766113f, 0.382813f, 0.781250f, 0.397949f, 0.0625f, -29.0625f, 30.0000f, 31, 31}, // 6d2a + {0.700684f, 0.405273f, 0.715820f, 0.420410f, 0.0625f, -29.0625f, 30.0000f, 31, 31}, // 6d2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d2d @@ -9117,23 +9418,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d3a - {0.910156f, 0.382813f, 0.925293f, 0.397949f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 6d3b + {0.315918f, 0.406250f, 0.331055f, 0.421387f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 6d3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d3d - {0.808105f, 0.096680f, 0.823730f, 0.112305f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6d3e + {0.951660f, 0.116211f, 0.967285f, 0.131836f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 6d3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d40 - {0.824219f, 0.096680f, 0.839844f, 0.112305f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 6d41 + {0.967773f, 0.116211f, 0.983398f, 0.131836f, -0.8125f, -28.9375f, 30.0000f, 32, 32}, // 6d41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d43 - {0.840332f, 0.096680f, 0.855957f, 0.112305f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 6d44 - {0.833496f, 0.256836f, 0.848633f, 0.272461f, -0.6250f, -29.6250f, 30.0000f, 31, 32}, // 6d45 + {0.983887f, 0.116211f, 0.999512f, 0.131836f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 6d44 + {0.658691f, 0.279297f, 0.673828f, 0.294922f, -0.6250f, -29.6250f, 30.0000f, 31, 32}, // 6d45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d4a - {0.776367f, 0.615234f, 0.790527f, 0.630371f, -0.5625f, -28.8750f, 30.0000f, 29, 31}, // 6d4b + {0.044922f, 0.642090f, 0.059082f, 0.657227f, -0.5625f, -28.8750f, 30.0000f, 29, 31}, // 6d4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d4e @@ -9150,7 +9451,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d5b - {0.849121f, 0.256836f, 0.864746f, 0.271973f, -0.6250f, -28.7500f, 30.0000f, 32, 31}, // 6d5c + {0.333984f, 0.280273f, 0.349609f, 0.295410f, -0.6250f, -28.7500f, 30.0000f, 32, 31}, // 6d5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d5f @@ -9160,25 +9461,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d65 - {0.898438f, 0.256836f, 0.914063f, 0.271973f, -0.7500f, -29.4375f, 30.0000f, 32, 31}, // 6d66 + {0.787109f, 0.280762f, 0.802734f, 0.295898f, -0.7500f, -29.4375f, 30.0000f, 32, 31}, // 6d66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d69 - {0.914551f, 0.256836f, 0.930176f, 0.271973f, -0.1875f, -28.8750f, 30.0000f, 32, 31}, // 6d6a + {0.803223f, 0.280762f, 0.818848f, 0.295898f, -0.1875f, -28.8750f, 30.0000f, 32, 31}, // 6d6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d6d - {0.876465f, 0.096680f, 0.892090f, 0.112305f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 6d6e + {0.875488f, 0.116699f, 0.891113f, 0.132324f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 6d6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d73 - {0.892578f, 0.096680f, 0.908203f, 0.112305f, -0.4375f, -29.4375f, 30.0000f, 32, 32}, // 6d74 + {0.916016f, 0.117188f, 0.931641f, 0.132813f, -0.4375f, -29.4375f, 30.0000f, 32, 32}, // 6d74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d76 - {0.908691f, 0.096680f, 0.924316f, 0.112305f, -0.7500f, -29.3125f, 30.0000f, 32, 32}, // 6d77 - {0.968750f, 0.256836f, 0.984375f, 0.271973f, -0.7500f, -28.0000f, 30.0000f, 32, 31}, // 6d78 + {0.096680f, 0.118164f, 0.112305f, 0.133789f, -0.7500f, -29.3125f, 30.0000f, 32, 32}, // 6d77 + {0.192383f, 0.281738f, 0.208008f, 0.296875f, -0.7500f, -28.0000f, 30.0000f, 32, 31}, // 6d78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d7b @@ -9194,7 +9495,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d87 - {0.843750f, 0.442871f, 0.858398f, 0.458496f, -0.1250f, -29.0000f, 30.0000f, 30, 32}, // 6d88 + {0.284180f, 0.462891f, 0.298828f, 0.478516f, -0.1250f, -29.0000f, 30.0000f, 30, 32}, // 6d88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d8b @@ -9211,7 +9512,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d98 - {0.274902f, 0.257324f, 0.290527f, 0.272461f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 6d99 + {0.512207f, 0.281738f, 0.527832f, 0.296875f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 6d99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6d9c @@ -9233,10 +9534,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dae - {0.291016f, 0.257324f, 0.306641f, 0.272461f, -0.8750f, -28.5625f, 30.0000f, 32, 31}, // 6daf + {0.208496f, 0.282227f, 0.224121f, 0.297363f, -0.8750f, -28.5625f, 30.0000f, 32, 31}, // 6daf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db1 - {0.924805f, 0.096680f, 0.940430f, 0.112305f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 6db2 + {0.112793f, 0.118164f, 0.128418f, 0.133789f, -0.5000f, -29.1875f, 30.0000f, 32, 32}, // 6db2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db5 @@ -9246,7 +9547,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6db9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dbb - {0.464844f, 0.257324f, 0.480469f, 0.272461f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 6dbc + {0.528320f, 0.282227f, 0.543945f, 0.297363f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 6dbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dbf @@ -9267,7 +9568,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dd0 - {0.145508f, 0.176270f, 0.161621f, 0.191406f, -1.1250f, -28.8750f, 30.0000f, 33, 31}, // 6dd1 + {0.257813f, 0.192871f, 0.273926f, 0.208008f, -1.1250f, -28.8750f, 30.0000f, 33, 31}, // 6dd1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dd4 @@ -9283,7 +9584,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ddf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6de0 - {0.940918f, 0.096680f, 0.956543f, 0.112305f, -0.6250f, -29.4375f, 30.0000f, 32, 32}, // 6de1 + {0.128906f, 0.118652f, 0.144531f, 0.134277f, -0.6250f, -29.4375f, 30.0000f, 32, 32}, // 6de1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6de2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6de3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6de4 @@ -9299,17 +9600,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6def {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df0 - {0.512695f, 0.257324f, 0.528320f, 0.272461f, -0.6875f, -28.2500f, 30.0000f, 32, 31}, // 6df1 + {0.643066f, 0.282227f, 0.658691f, 0.297363f, -0.6875f, -28.2500f, 30.0000f, 32, 31}, // 6df1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df6 - {0.684082f, 0.443359f, 0.699707f, 0.458008f, -0.3750f, -28.1250f, 30.0000f, 32, 30}, // 6df7 + {0.810547f, 0.462891f, 0.826172f, 0.477539f, -0.3750f, -28.1250f, 30.0000f, 32, 30}, // 6df7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6df9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dfa - {0.625488f, 0.257324f, 0.641113f, 0.272461f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 6dfb + {0.691406f, 0.282227f, 0.707031f, 0.297363f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 6dfb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6dfe @@ -9319,13 +9620,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e04 - {0.957031f, 0.096680f, 0.972656f, 0.112305f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 6e05 + {0.770020f, 0.118652f, 0.785645f, 0.134277f, -0.8750f, -29.0000f, 30.0000f, 32, 32}, // 6e05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e06 - {0.307129f, 0.522949f, 0.322266f, 0.537598f, -0.8125f, -28.0625f, 30.0000f, 31, 30}, // 6e07 - {0.254883f, 0.257813f, 0.270508f, 0.272949f, -0.7500f, -28.8125f, 30.0000f, 32, 31}, // 6e08 - {0.370117f, 0.257813f, 0.385742f, 0.272949f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 6e09 + {0.354004f, 0.547363f, 0.369141f, 0.562012f, -0.8125f, -28.0625f, 30.0000f, 31, 30}, // 6e07 + {0.562012f, 0.282715f, 0.577637f, 0.297852f, -0.7500f, -28.8125f, 30.0000f, 32, 31}, // 6e08 + {0.578125f, 0.282715f, 0.593750f, 0.297852f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 6e09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e0a - {0.717285f, 0.443359f, 0.732910f, 0.458008f, -0.5625f, -29.0625f, 30.0000f, 32, 30}, // 6e0b + {0.844727f, 0.462891f, 0.860352f, 0.477539f, -0.5625f, -29.0625f, 30.0000f, 32, 30}, // 6e0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e0e @@ -9333,7 +9634,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e12 - {0.193359f, 0.176270f, 0.209473f, 0.191406f, -0.6875f, -28.8750f, 30.0000f, 33, 31}, // 6e13 + {0.483398f, 0.193848f, 0.499512f, 0.208984f, -0.6875f, -28.8750f, 30.0000f, 33, 31}, // 6e13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e16 @@ -9341,36 +9642,36 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e1a - {0.973145f, 0.096680f, 0.988770f, 0.112305f, -0.4375f, -29.1250f, 30.0000f, 32, 32}, // 6e1b + {0.419434f, 0.119141f, 0.435059f, 0.134766f, -0.4375f, -29.1250f, 30.0000f, 32, 32}, // 6e1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e20 - {0.537598f, 0.097168f, 0.553223f, 0.112793f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 6e21 + {0.435547f, 0.119141f, 0.451172f, 0.134766f, -0.5625f, -29.0000f, 30.0000f, 32, 32}, // 6e21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e25 - {0.657227f, 0.522949f, 0.671875f, 0.538086f, -0.5000f, -28.6875f, 30.0000f, 30, 31}, // 6e26 + {0.657227f, 0.548340f, 0.671875f, 0.563477f, -0.5000f, -28.6875f, 30.0000f, 30, 31}, // 6e26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e28 - {0.171387f, 0.443848f, 0.187012f, 0.458496f, -0.9375f, -27.4375f, 30.0000f, 32, 30}, // 6e29 + {0.924805f, 0.463379f, 0.940430f, 0.478027f, -0.9375f, -27.4375f, 30.0000f, 32, 30}, // 6e29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e2b - {0.077148f, 0.523438f, 0.091797f, 0.538574f, -0.1250f, -28.8125f, 30.0000f, 30, 31}, // 6e2c + {0.199707f, 0.548828f, 0.214355f, 0.563965f, -0.1250f, -28.8125f, 30.0000f, 30, 31}, // 6e2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e2e - {0.658203f, 0.257813f, 0.673828f, 0.272949f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6e2f + {0.674316f, 0.282715f, 0.689941f, 0.297852f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 6e2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e31 - {0.942871f, 0.382813f, 0.958008f, 0.397949f, -0.3750f, -29.4375f, 30.0000f, 31, 31}, // 6e32 + {0.648926f, 0.406250f, 0.664063f, 0.421387f, -0.3750f, -29.4375f, 30.0000f, 31, 31}, // 6e32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e37 - {0.432617f, 0.258301f, 0.447754f, 0.273926f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 6e38 + {0.048340f, 0.283203f, 0.063477f, 0.298828f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 6e38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e3b @@ -9400,7 +9701,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e55 - {0.184082f, 0.523438f, 0.198730f, 0.538574f, 0.0000f, -28.9375f, 30.0000f, 30, 31}, // 6e56 + {0.514648f, 0.548828f, 0.529297f, 0.563965f, 0.0000f, -28.9375f, 30.0000f, 30, 31}, // 6e56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e59 @@ -9425,7 +9726,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e6e - {0.554688f, 0.444336f, 0.570313f, 0.458984f, -0.5000f, -27.8750f, 30.0000f, 32, 30}, // 6e6f + {0.940918f, 0.463379f, 0.956543f, 0.478027f, -0.5000f, -27.8750f, 30.0000f, 32, 30}, // 6e6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e72 @@ -9440,9 +9741,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e7d - {0.236816f, 0.383301f, 0.251953f, 0.398438f, -0.3750f, -29.1250f, 30.0000f, 31, 31}, // 6e7e - {0.387695f, 0.523438f, 0.402832f, 0.538086f, -0.5625f, -28.1250f, 30.0000f, 31, 30}, // 6e7f - {0.269043f, 0.383301f, 0.284180f, 0.398438f, -0.8750f, -28.8750f, 30.0000f, 31, 31}, // 6e80 + {0.783203f, 0.407227f, 0.798340f, 0.422363f, -0.3750f, -29.1250f, 30.0000f, 31, 31}, // 6e7e + {0.045410f, 0.549316f, 0.060547f, 0.563965f, -0.5625f, -28.1250f, 30.0000f, 31, 30}, // 6e7f + {0.798828f, 0.407227f, 0.813965f, 0.422363f, -0.8750f, -28.8750f, 30.0000f, 31, 31}, // 6e80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e83 @@ -9458,20 +9759,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e8f - {0.333496f, 0.383301f, 0.348633f, 0.398438f, -0.5625f, -28.0000f, 30.0000f, 31, 31}, // 6e90 + {0.495605f, 0.407715f, 0.510742f, 0.422852f, -0.5625f, -28.0000f, 30.0000f, 31, 31}, // 6e90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e95 - {0.480957f, 0.258301f, 0.496094f, 0.273926f, -0.3750f, -29.3125f, 30.0000f, 31, 32}, // 6e96 + {0.063965f, 0.283691f, 0.079102f, 0.299316f, -0.3750f, -29.3125f, 30.0000f, 31, 32}, // 6e96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e9c - {0.192383f, 0.258789f, 0.208008f, 0.273926f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 6e9d + {0.079590f, 0.283691f, 0.095215f, 0.298828f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 6e9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6e9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ea0 @@ -9496,7 +9797,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb5 - {0.668457f, 0.097168f, 0.684082f, 0.112793f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 6eb6 + {0.675293f, 0.119141f, 0.690918f, 0.134766f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 6eb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eb9 @@ -9511,19 +9812,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec4 - {0.224121f, 0.259277f, 0.239746f, 0.274414f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 6ec5 + {0.594238f, 0.283691f, 0.609863f, 0.298828f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 6ec5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ec9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eca - {0.856445f, 0.097168f, 0.872070f, 0.112793f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 6ecb + {0.376953f, 0.120605f, 0.392578f, 0.136230f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 6ecb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ecc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ecd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ece {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ecf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ed0 - {0.349121f, 0.383301f, 0.364258f, 0.398438f, -0.5625f, -28.3750f, 30.0000f, 31, 31}, // 6ed1 + {0.632813f, 0.407715f, 0.647949f, 0.422852f, -0.5625f, -28.3750f, 30.0000f, 31, 31}, // 6ed1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ed2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ed3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ed4 @@ -9535,14 +9836,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6edb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6edc - {0.208496f, 0.259766f, 0.224121f, 0.274902f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 6edd - {0.623535f, 0.383301f, 0.638672f, 0.398438f, -0.7500f, -28.8750f, 30.0000f, 31, 31}, // 6ede + {0.610352f, 0.283691f, 0.625977f, 0.298828f, -0.7500f, -29.0625f, 30.0000f, 32, 31}, // 6edd + {0.684082f, 0.407715f, 0.699219f, 0.422852f, -0.7500f, -28.8750f, 30.0000f, 31, 31}, // 6ede {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6edf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee3 - {0.338379f, 0.261230f, 0.354004f, 0.276367f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 6ee4 + {0.144531f, 0.284180f, 0.160156f, 0.299316f, -0.8750f, -29.0000f, 30.0000f, 32, 31}, // 6ee4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ee7 @@ -9558,7 +9859,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef3 - {0.386230f, 0.264160f, 0.401855f, 0.279297f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 6ef4 + {0.160645f, 0.284180f, 0.176270f, 0.299316f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 6ef4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ef7 @@ -9571,12 +9872,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6efe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6eff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f00 - {0.553711f, 0.097656f, 0.569336f, 0.113281f, -0.7500f, -29.5625f, 30.0000f, 32, 32}, // 6f01 - {0.544434f, 0.351074f, 0.560547f, 0.365723f, -1.3125f, -27.8750f, 30.0000f, 33, 30}, // 6f02 + {0.714844f, 0.120605f, 0.730469f, 0.136230f, -0.7500f, -29.5625f, 30.0000f, 32, 32}, // 6f01 + {0.884766f, 0.370605f, 0.900879f, 0.385254f, -1.3125f, -27.8750f, 30.0000f, 33, 30}, // 6f02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f05 - {0.946777f, 0.016113f, 0.962891f, 0.031738f, -1.1875f, -29.1250f, 30.0000f, 33, 32}, // 6f06 + {0.705566f, 0.038574f, 0.721680f, 0.054199f, -1.1875f, -29.1250f, 30.0000f, 33, 32}, // 6f06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f09 @@ -9585,12 +9886,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f0e - {0.112793f, 0.264648f, 0.128418f, 0.279785f, -0.6875f, -28.0625f, 30.0000f, 32, 31}, // 6f0f + {0.112305f, 0.284668f, 0.127930f, 0.299805f, -0.6875f, -28.0625f, 30.0000f, 32, 31}, // 6f0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f13 - {0.286133f, 0.098145f, 0.301758f, 0.113770f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 6f14 + {0.840820f, 0.120605f, 0.856445f, 0.136230f, -0.8750f, -29.2500f, 30.0000f, 32, 32}, // 6f14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f17 @@ -9602,9 +9903,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f1f - {0.963379f, 0.016113f, 0.979492f, 0.031738f, -1.1875f, -29.1875f, 30.0000f, 33, 32}, // 6f20 + {0.400879f, 0.040039f, 0.416992f, 0.055664f, -1.1875f, -29.1875f, 30.0000f, 33, 32}, // 6f20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f21 - {0.302246f, 0.098145f, 0.317871f, 0.113770f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 6f22 + {0.856934f, 0.121094f, 0.872559f, 0.136719f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 6f22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f25 @@ -9613,8 +9914,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f2a - {0.370605f, 0.176270f, 0.386719f, 0.191406f, -0.9375f, -28.2500f, 30.0000f, 33, 31}, // 6f2b - {0.318359f, 0.098145f, 0.333984f, 0.113770f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 6f2c + {0.500000f, 0.193848f, 0.516113f, 0.208984f, -0.9375f, -28.2500f, 30.0000f, 33, 31}, // 6f2b + {0.209473f, 0.122559f, 0.225098f, 0.138184f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 6f2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f2f @@ -9626,7 +9927,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f37 - {0.486816f, 0.098145f, 0.502441f, 0.113770f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 6f38 + {0.225586f, 0.122559f, 0.241211f, 0.138184f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 6f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f3b @@ -9654,7 +9955,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f53 - {0.655273f, 0.383301f, 0.670410f, 0.398438f, -0.3125f, -28.6875f, 30.0000f, 31, 31}, // 6f54 + {0.766602f, 0.407715f, 0.781738f, 0.422852f, -0.3125f, -28.6875f, 30.0000f, 31, 31}, // 6f54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f57 @@ -9662,15 +9963,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f5b - {0.402344f, 0.264648f, 0.417969f, 0.279785f, -0.4375f, -29.2500f, 30.0000f, 32, 31}, // 6f5c + {0.128418f, 0.284668f, 0.144043f, 0.299805f, -0.4375f, -29.2500f, 30.0000f, 32, 31}, // 6f5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f5e - {0.078613f, 0.444336f, 0.093262f, 0.459961f, -0.3125f, -29.4375f, 30.0000f, 30, 32}, // 6f5f + {0.299316f, 0.463379f, 0.313965f, 0.479004f, -0.3125f, -29.4375f, 30.0000f, 30, 32}, // 6f5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f63 - {0.211426f, 0.586426f, 0.226074f, 0.601074f, 0.0625f, -27.8750f, 30.0000f, 30, 30}, // 6f64 + {0.565430f, 0.615234f, 0.580078f, 0.629883f, 0.0625f, -27.8750f, 30.0000f, 30, 30}, // 6f64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f65 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f67 @@ -9680,7 +9981,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f6d - {0.314453f, 0.444336f, 0.329102f, 0.459961f, -0.3125f, -29.0000f, 30.0000f, 30, 32}, // 6f6e + {0.957031f, 0.463379f, 0.971680f, 0.479004f, -0.3125f, -29.0000f, 30.0000f, 30, 32}, // 6f6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f71 @@ -9702,7 +10003,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f83 - {0.307129f, 0.265137f, 0.322754f, 0.280273f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 6f84 + {0.176758f, 0.284668f, 0.192383f, 0.299805f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 6f84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6f87 @@ -9762,10 +10063,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fbf - {0.502930f, 0.098145f, 0.518555f, 0.113770f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 6fc0 - {0.725586f, 0.523438f, 0.740234f, 0.538574f, -0.3750f, -28.5000f, 30.0000f, 30, 31}, // 6fc1 + {0.241699f, 0.122559f, 0.257324f, 0.138184f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 6fc0 + {0.061035f, 0.549316f, 0.075684f, 0.564453f, -0.3750f, -28.5000f, 30.0000f, 30, 31}, // 6fc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fc2 - {0.459961f, 0.098633f, 0.475586f, 0.114258f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 6fc3 + {0.550293f, 0.122559f, 0.565918f, 0.138184f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 6fc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fc6 @@ -9805,11 +10106,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fe8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fe9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fea - {0.000000f, 0.266113f, 0.015625f, 0.281250f, -0.6250f, -29.3125f, 30.0000f, 32, 31}, // 6feb + {0.016113f, 0.285156f, 0.031738f, 0.300293f, -0.6250f, -29.3125f, 30.0000f, 32, 31}, // 6feb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fee - {0.016113f, 0.267090f, 0.031738f, 0.282227f, -0.8125f, -28.2500f, 30.0000f, 32, 31}, // 6fef + {0.000000f, 0.286133f, 0.015625f, 0.301270f, -0.8125f, -28.2500f, 30.0000f, 32, 31}, // 6fef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ff0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ff1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ff2 @@ -9824,7 +10125,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ffb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ffc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6ffd - {0.714355f, 0.098633f, 0.729980f, 0.114258f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 6ffe + {0.566406f, 0.122559f, 0.582031f, 0.138184f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 6ffe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 6fff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7000 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7001 @@ -9870,7 +10171,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7029 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 702a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 702b - {0.519043f, 0.099609f, 0.534668f, 0.115234f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 702c + {0.691406f, 0.123047f, 0.707031f, 0.138672f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 702c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 702d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 702e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 702f @@ -9933,17 +10234,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7068 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7069 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 706a - {0.740723f, 0.523438f, 0.755371f, 0.538574f, 0.5000f, -28.5000f, 30.0000f, 30, 31}, // 706b + {0.468262f, 0.549316f, 0.482910f, 0.564453f, 0.5000f, -28.5000f, 30.0000f, 30, 31}, // 706b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 706c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 706d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 706e - {0.064453f, 0.267578f, 0.079590f, 0.283203f, -0.5625f, -28.4375f, 30.0000f, 31, 32}, // 706f - {0.570801f, 0.444336f, 0.586426f, 0.458984f, -1.0625f, -27.5000f, 30.0000f, 32, 30}, // 7070 + {0.726074f, 0.286133f, 0.741211f, 0.301758f, -0.5625f, -28.4375f, 30.0000f, 31, 32}, // 706f + {0.972168f, 0.463379f, 0.987793f, 0.478027f, -1.0625f, -27.5000f, 30.0000f, 32, 30}, // 7070 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7071 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7073 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7074 - {0.137695f, 0.523926f, 0.152832f, 0.538574f, -0.4375f, -27.7500f, 30.0000f, 31, 30}, // 7075 + {0.560547f, 0.549316f, 0.575684f, 0.563965f, -0.4375f, -27.7500f, 30.0000f, 31, 30}, // 7075 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7076 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7077 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7078 @@ -9951,7 +10252,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 707a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 707b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 707c - {0.032227f, 0.268066f, 0.047852f, 0.283203f, -0.4375f, -28.5625f, 30.0000f, 32, 31}, // 707d + {0.741699f, 0.286133f, 0.757324f, 0.301270f, -0.4375f, -28.5625f, 30.0000f, 32, 31}, // 707d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 707e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 707f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7080 @@ -9963,12 +10264,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7086 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7087 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7088 - {0.702637f, 0.383301f, 0.717773f, 0.398438f, -1.0000f, -28.8750f, 30.0000f, 31, 31}, // 7089 - {0.209473f, 0.100098f, 0.225098f, 0.115723f, -0.2500f, -29.1875f, 30.0000f, 32, 32}, // 708a + {0.206543f, 0.408203f, 0.221680f, 0.423340f, -1.0000f, -28.8750f, 30.0000f, 31, 31}, // 7089 + {0.730957f, 0.123047f, 0.746582f, 0.138672f, -0.2500f, -29.1875f, 30.0000f, 32, 32}, // 708a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 708b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 708c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 708d - {0.048340f, 0.268066f, 0.063477f, 0.283691f, -0.0625f, -28.8750f, 30.0000f, 31, 32}, // 708e + {0.253906f, 0.286621f, 0.269043f, 0.302246f, -0.0625f, -28.8750f, 30.0000f, 31, 32}, // 708e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 708f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7090 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7091 @@ -9999,7 +10300,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ac - {0.225586f, 0.100098f, 0.241211f, 0.115723f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 70ad + {0.747070f, 0.123047f, 0.762695f, 0.138672f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 70ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70b0 @@ -10011,8 +10312,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70b8 - {0.241699f, 0.100098f, 0.257324f, 0.115723f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 70b9 - {0.632324f, 0.444336f, 0.646973f, 0.459961f, -0.1875f, -29.1875f, 30.0000f, 30, 32}, // 70ba + {0.601074f, 0.123535f, 0.616699f, 0.139160f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 70b9 + {0.330566f, 0.464355f, 0.345215f, 0.479980f, -0.1875f, -29.1875f, 30.0000f, 30, 32}, // 70ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70bd @@ -10026,7 +10327,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70c7 - {0.781738f, 0.383301f, 0.796875f, 0.398438f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 70c8 + {0.476563f, 0.408203f, 0.491699f, 0.423340f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 70c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70cb @@ -10063,7 +10364,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ec - {0.080078f, 0.268066f, 0.095703f, 0.283203f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 70ed + {0.224609f, 0.287109f, 0.240234f, 0.302246f, -0.6875f, -28.8750f, 30.0000f, 32, 31}, // 70ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 70f0 @@ -10115,12 +10416,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 711e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 711f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7120 - {0.257813f, 0.100098f, 0.273438f, 0.115723f, -0.6875f, -29.3750f, 30.0000f, 32, 32}, // 7121 + {0.617188f, 0.123535f, 0.632813f, 0.139160f, -0.6875f, -29.3750f, 30.0000f, 32, 32}, // 7121 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7122 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7123 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7124 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7125 - {0.367188f, 0.101563f, 0.382813f, 0.117188f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 7126 + {0.048340f, 0.124023f, 0.063965f, 0.139648f, -0.5625f, -29.0625f, 30.0000f, 32, 32}, // 7126 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7127 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7128 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7129 @@ -10136,13 +10437,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7133 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7134 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7135 - {0.323242f, 0.269043f, 0.338379f, 0.284668f, -0.1875f, -29.1875f, 30.0000f, 31, 32}, // 7136 + {0.269531f, 0.287109f, 0.284668f, 0.302734f, -0.1875f, -29.1875f, 30.0000f, 31, 32}, // 7136 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7137 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7138 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7139 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 713a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 713b - {0.427246f, 0.104492f, 0.442871f, 0.120117f, -0.3125f, -28.8750f, 30.0000f, 32, 32}, // 713c + {0.064453f, 0.124023f, 0.080078f, 0.139648f, -0.3125f, -28.8750f, 30.0000f, 32, 32}, // 713c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 713d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 713e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 713f @@ -10171,7 +10472,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7156 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7157 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7158 - {0.160156f, 0.270508f, 0.175781f, 0.285645f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 7159 + {0.285156f, 0.287109f, 0.300781f, 0.302246f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 7159 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 715a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 715b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 715c @@ -10185,14 +10486,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7164 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7165 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7166 - {0.215332f, 0.523926f, 0.230469f, 0.538574f, 0.0000f, -27.6875f, 30.0000f, 31, 30}, // 7167 + {0.638184f, 0.549316f, 0.653320f, 0.563965f, 0.0000f, -27.6875f, 30.0000f, 31, 30}, // 7167 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7168 - {0.443359f, 0.104980f, 0.458984f, 0.120605f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 7169 + {0.080566f, 0.124023f, 0.096191f, 0.139648f, -0.5625f, -28.9375f, 30.0000f, 32, 32}, // 7169 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 716a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 716b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 716c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 716d - {0.128906f, 0.106445f, 0.144531f, 0.122070f, -0.3750f, -28.9375f, 30.0000f, 32, 32}, // 716e + {0.633301f, 0.124512f, 0.648926f, 0.140137f, -0.3750f, -28.9375f, 30.0000f, 32, 32}, // 716e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 716f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7170 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7171 @@ -10241,7 +10542,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 719c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 719d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 719e - {0.354492f, 0.270508f, 0.370117f, 0.285645f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 719f + {0.301270f, 0.287109f, 0.316895f, 0.302246f, -0.8750f, -28.9375f, 30.0000f, 32, 31}, // 719f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71a2 @@ -10259,7 +10560,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71b0 - {0.145020f, 0.106445f, 0.160645f, 0.122070f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 71b1 + {0.649414f, 0.124512f, 0.665039f, 0.140137f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 71b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71b4 @@ -10277,12 +10578,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c2 - {0.334473f, 0.106934f, 0.350098f, 0.122559f, -0.6875f, -28.9375f, 30.0000f, 32, 32}, // 71c3 + {0.145020f, 0.125488f, 0.160645f, 0.141113f, -0.6875f, -28.9375f, 30.0000f, 32, 32}, // 71c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c7 - {0.350586f, 0.106934f, 0.366211f, 0.122559f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 71c8 + {0.177246f, 0.125488f, 0.192871f, 0.141113f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 71c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71cb @@ -10311,7 +10612,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e4 - {0.979980f, 0.016113f, 0.996094f, 0.031738f, -1.0625f, -28.8750f, 30.0000f, 33, 32}, // 71e5 + {0.740723f, 0.040039f, 0.756836f, 0.055664f, -1.0625f, -28.8750f, 30.0000f, 33, 32}, // 71e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 71e8 @@ -10344,7 +10645,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7203 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7204 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7205 - {0.000000f, 0.107910f, 0.015625f, 0.123535f, -0.8750f, -28.8750f, 30.0000f, 32, 32}, // 7206 + {0.193359f, 0.125488f, 0.208984f, 0.141113f, -0.8750f, -28.8750f, 30.0000f, 32, 32}, // 7206 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7207 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7208 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7209 @@ -10391,8 +10692,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7232 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7233 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7234 - {0.641602f, 0.270508f, 0.656738f, 0.286133f, -0.1250f, -29.3125f, 30.0000f, 31, 32}, // 7235 - {0.822754f, 0.615234f, 0.836914f, 0.630371f, 0.8125f, -28.8125f, 30.0000f, 29, 31}, // 7236 + {0.032227f, 0.288086f, 0.047363f, 0.303711f, -0.1250f, -29.3125f, 30.0000f, 31, 32}, // 7235 + {0.075195f, 0.642090f, 0.089355f, 0.657227f, 0.8125f, -28.8125f, 30.0000f, 29, 31}, // 7236 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7237 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7238 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7239 @@ -10409,8 +10710,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7244 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7245 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7246 - {0.733398f, 0.444336f, 0.748047f, 0.459961f, -0.6250f, -28.9375f, 30.0000f, 30, 32}, // 7247 - {0.668945f, 0.176270f, 0.685059f, 0.191406f, -1.0000f, -28.5625f, 30.0000f, 33, 31}, // 7248 + {0.393066f, 0.464844f, 0.407715f, 0.480469f, -0.6250f, -28.9375f, 30.0000f, 30, 32}, // 7247 + {0.792969f, 0.193848f, 0.809082f, 0.208984f, -1.0000f, -28.5625f, 30.0000f, 33, 31}, // 7248 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7249 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 724a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 724b @@ -10429,7 +10730,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7258 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7259 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 725a - {0.230957f, 0.523926f, 0.245605f, 0.539063f, 0.4375f, -28.9375f, 30.0000f, 30, 31}, // 725b + {0.015137f, 0.549805f, 0.029785f, 0.564941f, 0.4375f, -28.9375f, 30.0000f, 30, 31}, // 725b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 725c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 725d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 725e @@ -10441,9 +10742,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7264 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7265 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7266 - {0.016113f, 0.107910f, 0.031738f, 0.123535f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 7267 + {0.161133f, 0.125977f, 0.176758f, 0.141602f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 7267 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7268 - {0.748535f, 0.444336f, 0.763184f, 0.459961f, 0.0000f, -28.8750f, 30.0000f, 30, 32}, // 7269 + {0.408203f, 0.464844f, 0.422852f, 0.480469f, 0.0000f, -28.8750f, 30.0000f, 30, 32}, // 7269 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 726a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 726b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 726c @@ -10452,14 +10753,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 726f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7270 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7271 - {0.096191f, 0.270996f, 0.111816f, 0.286133f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 7272 + {0.463867f, 0.288086f, 0.479492f, 0.303223f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 7272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7273 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7274 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7275 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7276 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7277 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7278 - {0.814453f, 0.383301f, 0.829590f, 0.398438f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 7279 + {0.538086f, 0.408203f, 0.553223f, 0.423340f, -0.5000f, -28.9375f, 30.0000f, 31, 31}, // 7279 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 727a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 727b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 727c @@ -10498,7 +10799,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 729d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 729e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 729f - {0.583496f, 0.016602f, 0.599609f, 0.032227f, -1.0625f, -29.6250f, 30.0000f, 33, 32}, // 72a0 + {0.875977f, 0.040039f, 0.892090f, 0.055664f, -1.0625f, -29.6250f, 30.0000f, 33, 32}, // 72a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72a3 @@ -10510,17 +10811,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ab - {0.879395f, 0.383301f, 0.894531f, 0.398438f, 0.3125f, -28.8125f, 30.0000f, 31, 31}, // 72ac + {0.553711f, 0.408203f, 0.568848f, 0.423340f, 0.3125f, -28.8125f, 30.0000f, 31, 31}, // 72ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ae - {0.895020f, 0.383301f, 0.910156f, 0.398438f, -0.1875f, -28.3125f, 30.0000f, 31, 31}, // 72af + {0.664551f, 0.408203f, 0.679688f, 0.423340f, -0.1875f, -28.3125f, 30.0000f, 31, 31}, // 72af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b5 - {0.189941f, 0.383789f, 0.205078f, 0.398926f, -0.6875f, -28.6875f, 30.0000f, 31, 31}, // 72b6 + {0.046875f, 0.408691f, 0.062012f, 0.423828f, -0.6875f, -28.6875f, 30.0000f, 31, 31}, // 72b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72b9 @@ -10532,7 +10833,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72c1 - {0.430664f, 0.383789f, 0.445801f, 0.398926f, -0.5625f, -28.2500f, 30.0000f, 31, 31}, // 72c2 + {0.173828f, 0.408691f, 0.188965f, 0.423828f, -0.5625f, -28.2500f, 30.0000f, 31, 31}, // 72c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72c5 @@ -10571,15 +10872,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72e8 - {0.128906f, 0.270996f, 0.144531f, 0.286133f, -0.5625f, -28.7500f, 30.0000f, 32, 31}, // 72e9 + {0.479980f, 0.288574f, 0.495605f, 0.303711f, -0.5625f, -28.7500f, 30.0000f, 32, 31}, // 72e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72eb - {0.176270f, 0.270996f, 0.191895f, 0.286133f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 72ec - {0.561523f, 0.270996f, 0.577148f, 0.286133f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 72ed + {0.496094f, 0.288574f, 0.511719f, 0.303711f, -1.0625f, -28.8750f, 30.0000f, 32, 31}, // 72ec + {0.757813f, 0.288574f, 0.773438f, 0.303711f, -1.1875f, -28.9375f, 30.0000f, 32, 31}, // 72ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72f0 - {0.865234f, 0.270996f, 0.880859f, 0.286133f, -1.0625f, -28.6875f, 30.0000f, 32, 31}, // 72f1 + {0.317383f, 0.289551f, 0.333008f, 0.304688f, -1.0625f, -28.6875f, 30.0000f, 32, 31}, // 72f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 72f4 @@ -10621,11 +10922,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7318 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7319 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 731a - {0.763672f, 0.444336f, 0.779297f, 0.458984f, -0.5625f, -28.2500f, 30.0000f, 32, 30}, // 731b + {0.907715f, 0.464844f, 0.923340f, 0.479492f, -0.5625f, -28.2500f, 30.0000f, 32, 30}, // 731b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 731c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 731d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 731e - {0.528809f, 0.271484f, 0.544434f, 0.286621f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 731f + {0.834961f, 0.289551f, 0.850586f, 0.304688f, -0.5625f, -28.8750f, 30.0000f, 32, 31}, // 731f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7320 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7321 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7322 @@ -10637,10 +10938,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7328 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7329 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 732a - {0.593750f, 0.271484f, 0.609375f, 0.286621f, -1.3125f, -28.7500f, 30.0000f, 32, 31}, // 732b + {0.350098f, 0.291016f, 0.365723f, 0.306152f, -1.3125f, -28.7500f, 30.0000f, 32, 31}, // 732b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 732c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 732d - {0.814941f, 0.271484f, 0.830566f, 0.286621f, -0.3750f, -29.3125f, 30.0000f, 32, 31}, // 732e + {0.402344f, 0.291016f, 0.417969f, 0.306152f, -0.3750f, -29.3125f, 30.0000f, 32, 31}, // 732e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 732f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7330 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7331 @@ -10648,7 +10949,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7333 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7334 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7335 - {0.032227f, 0.107910f, 0.047852f, 0.123535f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 7336 + {0.000000f, 0.126953f, 0.015625f, 0.142578f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 7336 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7337 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7338 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7339 @@ -10657,12 +10958,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 733c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 733d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 733e - {0.880859f, 0.016602f, 0.896973f, 0.032227f, -0.7500f, -29.0000f, 30.0000f, 33, 32}, // 733f + {0.892578f, 0.040527f, 0.908691f, 0.056152f, -0.7500f, -29.0000f, 30.0000f, 33, 32}, // 733f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7340 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7341 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7342 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7343 - {0.162109f, 0.176758f, 0.178223f, 0.191895f, -0.9375f, -28.8125f, 30.0000f, 33, 31}, // 7344 + {0.868652f, 0.195313f, 0.884766f, 0.210449f, -0.9375f, -28.8125f, 30.0000f, 33, 31}, // 7344 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7345 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7346 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7347 @@ -10693,7 +10994,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7360 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7361 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7362 - {0.048340f, 0.109375f, 0.063965f, 0.125000f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 7363 + {0.016113f, 0.126953f, 0.031738f, 0.142578f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 7363 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7364 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7365 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7366 @@ -10708,7 +11009,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 736f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7370 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7371 - {0.600098f, 0.017090f, 0.616211f, 0.032715f, -1.1250f, -29.2500f, 30.0000f, 33, 32}, // 7372 + {0.242676f, 0.041992f, 0.258789f, 0.057617f, -1.1250f, -29.2500f, 30.0000f, 33, 32}, // 7372 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7373 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7374 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7375 @@ -10726,14 +11027,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7381 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7382 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7383 - {0.384766f, 0.615723f, 0.398926f, 0.630859f, 0.8125f, -28.6250f, 30.0000f, 29, 31}, // 7384 + {0.546875f, 0.642090f, 0.561035f, 0.657227f, 0.8125f, -28.6250f, 30.0000f, 29, 31}, // 7384 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7385 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7386 - {0.796875f, 0.444336f, 0.811523f, 0.459961f, 0.1250f, -29.2500f, 30.0000f, 30, 32}, // 7387 + {0.876465f, 0.464844f, 0.891113f, 0.480469f, 0.1250f, -29.2500f, 30.0000f, 30, 32}, // 7387 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7388 - {0.354004f, 0.706055f, 0.367676f, 0.719238f, 1.5000f, -26.5625f, 30.0000f, 28, 27}, // 7389 + {0.094727f, 0.749512f, 0.108398f, 0.762695f, 1.5000f, -26.5625f, 30.0000f, 28, 27}, // 7389 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 738a - {0.748047f, 0.691406f, 0.762207f, 0.704590f, 0.7500f, -27.0000f, 30.0000f, 29, 27}, // 738b + {0.276855f, 0.731934f, 0.291016f, 0.745117f, 0.7500f, -27.0000f, 30.0000f, 29, 27}, // 738b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 738c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 738d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 738e @@ -10763,7 +11064,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73a8 - {0.489258f, 0.444824f, 0.504883f, 0.459473f, -0.5000f, -27.3750f, 30.0000f, 32, 30}, // 73a9 + {0.860840f, 0.465332f, 0.876465f, 0.479980f, -0.5000f, -27.3750f, 30.0000f, 32, 30}, // 73a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ac @@ -10799,7 +11100,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73cc - {0.064453f, 0.109375f, 0.080078f, 0.125000f, 0.0000f, -29.5000f, 30.0000f, 32, 32}, // 73cd + {0.032227f, 0.126953f, 0.047852f, 0.142578f, 0.0000f, -29.5000f, 30.0000f, 32, 32}, // 73cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73d0 @@ -10818,7 +11119,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73df - {0.881348f, 0.271484f, 0.896973f, 0.286621f, -0.0625f, -29.1250f, 30.0000f, 32, 31}, // 73e0 + {0.874023f, 0.291016f, 0.889648f, 0.306152f, -0.0625f, -29.1250f, 30.0000f, 32, 31}, // 73e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73e3 @@ -10831,7 +11132,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ec - {0.577637f, 0.271973f, 0.593262f, 0.287109f, -0.5000f, -28.3750f, 30.0000f, 32, 31}, // 73ed + {0.947754f, 0.291016f, 0.963379f, 0.306152f, -0.5000f, -28.3750f, 30.0000f, 32, 31}, // 73ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73f0 @@ -10848,15 +11149,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73fd - {0.322754f, 0.523926f, 0.337891f, 0.538574f, -0.3750f, -27.3750f, 30.0000f, 31, 30}, // 73fe + {0.030273f, 0.549805f, 0.045410f, 0.564453f, -0.3750f, -27.3750f, 30.0000f, 31, 30}, // 73fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 73ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7400 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7401 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7402 - {0.609863f, 0.271973f, 0.625488f, 0.287109f, -0.4375f, -28.9375f, 30.0000f, 32, 31}, // 7403 + {0.418457f, 0.291504f, 0.434082f, 0.306641f, -0.4375f, -28.9375f, 30.0000f, 32, 31}, // 7403 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7404 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7405 - {0.318848f, 0.620117f, 0.334473f, 0.633789f, -1.0000f, -27.2500f, 30.0000f, 32, 28}, // 7406 + {0.967285f, 0.652344f, 0.982910f, 0.666016f, -1.0000f, -27.2500f, 30.0000f, 32, 28}, // 7406 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7407 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7408 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7409 @@ -10902,7 +11203,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7431 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7432 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7433 - {0.674316f, 0.271973f, 0.689941f, 0.287109f, -1.0000f, -28.0625f, 30.0000f, 32, 31}, // 7434 + {0.434570f, 0.291504f, 0.450195f, 0.306641f, -1.0000f, -28.0625f, 30.0000f, 32, 31}, // 7434 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7435 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7436 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7437 @@ -11026,7 +11327,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74af - {0.721680f, 0.271973f, 0.737305f, 0.287109f, -0.8125f, -28.2500f, 30.0000f, 32, 31}, // 74b0 + {0.544434f, 0.291504f, 0.560059f, 0.306641f, -0.8125f, -28.2500f, 30.0000f, 32, 31}, // 74b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74b3 @@ -11039,7 +11340,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74bc - {0.586914f, 0.444824f, 0.602539f, 0.459473f, -0.4375f, -28.0000f, 30.0000f, 32, 30}, // 74bd + {0.826660f, 0.465820f, 0.842285f, 0.480469f, -0.4375f, -28.0000f, 30.0000f, 32, 30}, // 74bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74c0 @@ -11096,7 +11397,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f5 - {0.080566f, 0.109375f, 0.096191f, 0.125000f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 74f6 + {0.786133f, 0.127441f, 0.801758f, 0.143066f, -0.6250f, -29.3125f, 30.0000f, 32, 32}, // 74f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 74f9 @@ -11130,23 +11431,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7515 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7516 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7517 - {0.403320f, 0.523926f, 0.417969f, 0.539063f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 7518 + {0.076172f, 0.549805f, 0.090820f, 0.564941f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 7518 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7519 - {0.145020f, 0.271973f, 0.160156f, 0.287598f, 0.0000f, -29.0625f, 30.0000f, 31, 32}, // 751a + {0.915039f, 0.291504f, 0.930176f, 0.307129f, 0.0000f, -29.0625f, 30.0000f, 31, 32}, // 751a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 751b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 751c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 751d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 751e - {0.727051f, 0.615723f, 0.742188f, 0.629883f, -0.2500f, -28.7500f, 30.0000f, 31, 29}, // 751f + {0.180664f, 0.642578f, 0.195801f, 0.656738f, -0.2500f, -28.7500f, 30.0000f, 31, 29}, // 751f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7520 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7521 - {0.690430f, 0.271973f, 0.705566f, 0.287598f, -0.5625f, -29.1875f, 30.0000f, 31, 32}, // 7522 - {0.782715f, 0.271973f, 0.797852f, 0.287598f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 7523 + {0.819336f, 0.291992f, 0.834473f, 0.307617f, -0.5625f, -29.1875f, 30.0000f, 31, 32}, // 7522 + {0.890137f, 0.291992f, 0.905273f, 0.307617f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 7523 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7524 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7525 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7526 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7527 - {0.062500f, 0.646973f, 0.076660f, 0.661621f, -0.5000f, -27.6875f, 30.0000f, 29, 30}, // 7528 + {0.132324f, 0.674316f, 0.146484f, 0.688965f, -0.5000f, -27.6875f, 30.0000f, 29, 30}, // 7528 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7529 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 752a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 752b @@ -11154,18 +11455,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 752d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 752e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 752f - {0.823730f, 0.691406f, 0.836914f, 0.705566f, 2.0000f, -26.8750f, 30.0000f, 27, 29}, // 7530 - {0.798828f, 0.674316f, 0.811523f, 0.689941f, 2.0625f, -29.0000f, 30.0000f, 26, 32}, // 7531 - {0.038574f, 0.693359f, 0.051270f, 0.708008f, 2.1875f, -27.5625f, 30.0000f, 26, 30}, // 7532 - {0.664063f, 0.681152f, 0.676758f, 0.696289f, 2.4375f, -29.0000f, 30.0000f, 26, 31}, // 7533 + {0.054688f, 0.731445f, 0.067871f, 0.745605f, 2.0000f, -26.8750f, 30.0000f, 27, 29}, // 7530 + {0.158691f, 0.706055f, 0.171387f, 0.721680f, 2.0625f, -29.0000f, 30.0000f, 26, 32}, // 7531 + {0.108398f, 0.734375f, 0.121094f, 0.749023f, 2.1875f, -27.5625f, 30.0000f, 26, 30}, // 7532 + {0.719238f, 0.720215f, 0.731934f, 0.735352f, 2.4375f, -29.0000f, 30.0000f, 26, 31}, // 7533 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7534 - {0.209961f, 0.646973f, 0.224121f, 0.661621f, 2.4375f, -28.7500f, 30.0000f, 29, 30}, // 7535 + {0.523438f, 0.674805f, 0.537598f, 0.689453f, 2.4375f, -28.7500f, 30.0000f, 29, 30}, // 7535 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7536 - {0.286621f, 0.646973f, 0.300781f, 0.661621f, 0.5000f, -27.5000f, 30.0000f, 29, 30}, // 7537 + {0.014160f, 0.675293f, 0.028320f, 0.689941f, 0.5000f, -27.5000f, 30.0000f, 29, 30}, // 7537 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7538 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7539 - {0.136719f, 0.586914f, 0.151367f, 0.601563f, 1.1875f, -27.6875f, 30.0000f, 30, 30}, // 753a - {0.429199f, 0.586914f, 0.443848f, 0.601563f, 0.2500f, -28.0000f, 30.0000f, 30, 30}, // 753b + {0.940430f, 0.615234f, 0.955078f, 0.629883f, 1.1875f, -27.6875f, 30.0000f, 30, 30}, // 753a + {0.955566f, 0.615234f, 0.970215f, 0.629883f, 0.2500f, -28.0000f, 30.0000f, 30, 30}, // 753b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 753c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 753d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 753e @@ -11182,24 +11483,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7549 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 754a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 754b - {0.664063f, 0.444824f, 0.679688f, 0.459473f, -0.3750f, -27.5000f, 30.0000f, 32, 30}, // 754c + {0.891602f, 0.466309f, 0.907227f, 0.480957f, -0.3750f, -27.5000f, 30.0000f, 32, 30}, // 754c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 754d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 754e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 754f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7550 - {0.467773f, 0.523926f, 0.482422f, 0.539063f, -0.5000f, -29.1875f, 30.0000f, 30, 31}, // 7551 + {0.122559f, 0.549805f, 0.137207f, 0.564941f, -0.5000f, -29.1875f, 30.0000f, 30, 31}, // 7551 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7552 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7553 - {0.093750f, 0.444824f, 0.108398f, 0.460449f, 0.7500f, -29.1875f, 30.0000f, 30, 32}, // 7554 + {0.378418f, 0.465332f, 0.393066f, 0.480957f, 0.7500f, -29.1875f, 30.0000f, 30, 32}, // 7554 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7555 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7556 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7557 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7558 - {0.758301f, 0.615723f, 0.772461f, 0.630859f, 0.2500f, -28.5625f, 30.0000f, 29, 31}, // 7559 + {0.030273f, 0.643066f, 0.044434f, 0.658203f, 0.2500f, -28.5625f, 30.0000f, 29, 31}, // 7559 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 755a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 755b - {0.499512f, 0.523926f, 0.514160f, 0.539063f, 0.3125f, -29.1250f, 30.0000f, 30, 31}, // 755c - {0.096680f, 0.109375f, 0.112305f, 0.125000f, -0.3750f, -29.1250f, 30.0000f, 32, 32}, // 755d + {0.152832f, 0.549805f, 0.167480f, 0.564941f, 0.3125f, -29.1250f, 30.0000f, 30, 31}, // 755c + {0.802246f, 0.127441f, 0.817871f, 0.143066f, -0.3750f, -29.1250f, 30.0000f, 32, 32}, // 755d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 755e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 755f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7560 @@ -11207,21 +11508,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7562 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7563 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7564 - {0.523438f, 0.444824f, 0.538086f, 0.460449f, 1.2500f, -29.1875f, 30.0000f, 30, 32}, // 7565 + {0.345703f, 0.466797f, 0.360352f, 0.482422f, 1.2500f, -29.1875f, 30.0000f, 30, 32}, // 7565 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7566 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7567 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7568 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7569 - {0.112793f, 0.111328f, 0.128418f, 0.126953f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 756a - {0.459473f, 0.586914f, 0.474121f, 0.601563f, 0.4375f, -29.0625f, 30.0000f, 30, 30}, // 756b + {0.289063f, 0.127930f, 0.304688f, 0.143555f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 756a + {0.410156f, 0.615723f, 0.424805f, 0.630371f, 0.4375f, -29.0625f, 30.0000f, 30, 30}, // 756b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 756c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 756d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 756e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 756f - {0.493652f, 0.586914f, 0.508301f, 0.601563f, 0.1250f, -27.5625f, 30.0000f, 30, 30}, // 7570 + {0.212402f, 0.616211f, 0.227051f, 0.630859f, 0.1250f, -27.5625f, 30.0000f, 30, 30}, // 7570 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7571 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7572 - {0.514648f, 0.523926f, 0.529785f, 0.538574f, -0.3750f, -28.4375f, 30.0000f, 31, 30}, // 7573 + {0.184570f, 0.549805f, 0.199707f, 0.564453f, -0.3750f, -28.4375f, 30.0000f, 31, 30}, // 7573 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7574 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7575 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7576 @@ -11248,10 +11549,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 758b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 758c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 758d - {0.544434f, 0.177246f, 0.560547f, 0.192383f, -1.1250f, -28.8750f, 30.0000f, 33, 31}, // 758e + {0.370605f, 0.196777f, 0.386719f, 0.211914f, -1.1250f, -28.8750f, 30.0000f, 33, 31}, // 758e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 758f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7590 - {0.448242f, 0.272461f, 0.463867f, 0.287598f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 7591 + {0.851074f, 0.292480f, 0.866699f, 0.307617f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 7591 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7592 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7593 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7594 @@ -11277,14 +11578,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75aa - {0.161133f, 0.111816f, 0.176758f, 0.127441f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 75ab + {0.305176f, 0.127930f, 0.320801f, 0.143555f, -0.9375f, -29.2500f, 30.0000f, 32, 32}, // 75ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75b1 - {0.193359f, 0.111816f, 0.208984f, 0.127441f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 75b2 + {0.321289f, 0.127930f, 0.336914f, 0.143555f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 75b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75b5 @@ -11296,16 +11597,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75bd - {0.383301f, 0.111816f, 0.398926f, 0.127441f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 75be + {0.337402f, 0.127930f, 0.353027f, 0.143555f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 75be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c4 - {0.496582f, 0.272461f, 0.511719f, 0.288086f, -0.8750f, -29.2500f, 30.0000f, 31, 32}, // 75c5 + {0.983887f, 0.292480f, 0.999023f, 0.308105f, -0.8750f, -29.2500f, 30.0000f, 31, 32}, // 75c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c6 - {0.544922f, 0.272461f, 0.560547f, 0.287598f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 75c7 + {0.930664f, 0.292969f, 0.946289f, 0.308105f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 75c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75ca @@ -11322,17 +11623,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75d7 - {0.399414f, 0.111816f, 0.415039f, 0.127441f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 75d8 + {0.353516f, 0.127930f, 0.369141f, 0.143555f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 75d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75da - {0.684570f, 0.111816f, 0.700195f, 0.127441f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 75db + {0.257813f, 0.128418f, 0.273438f, 0.144043f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 75db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75e1 - {0.177246f, 0.112305f, 0.192871f, 0.127930f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 75e2 + {0.516602f, 0.129395f, 0.532227f, 0.145020f, -0.6875f, -29.0625f, 30.0000f, 32, 32}, // 75e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75e5 @@ -11350,7 +11651,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f3 - {0.569824f, 0.112793f, 0.585449f, 0.128418f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 75f4 + {0.532715f, 0.129395f, 0.548340f, 0.145020f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 75f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 75f7 @@ -11428,7 +11729,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 763f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7640 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7641 - {0.706055f, 0.272461f, 0.721680f, 0.287598f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 7642 + {0.963867f, 0.292969f, 0.979492f, 0.308105f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 7642 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7643 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7644 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7645 @@ -11444,11 +11745,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 764f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7650 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7651 - {0.737793f, 0.272461f, 0.753418f, 0.287598f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 7652 + {0.095703f, 0.293457f, 0.111328f, 0.308594f, -0.7500f, -29.1250f, 30.0000f, 32, 31}, // 7652 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7653 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7654 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7655 - {0.585938f, 0.112793f, 0.601563f, 0.128418f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 7656 + {0.818359f, 0.129395f, 0.833984f, 0.145020f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 7656 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7657 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7658 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7659 @@ -11484,20 +11785,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7677 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7678 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7679 - {0.753906f, 0.272461f, 0.769531f, 0.287598f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 767a - {0.812012f, 0.444824f, 0.827637f, 0.459473f, -0.3125f, -29.1250f, 30.0000f, 32, 30}, // 767b - {0.798340f, 0.272461f, 0.813965f, 0.287598f, -0.5000f, -28.9375f, 30.0000f, 32, 31}, // 767c - {0.988281f, 0.129395f, 0.999512f, 0.145020f, 3.9375f, -29.0625f, 30.0000f, 23, 32}, // 767d - {0.591309f, 0.646973f, 0.605469f, 0.661621f, 0.9375f, -27.4375f, 30.0000f, 29, 30}, // 767e + {0.366211f, 0.294434f, 0.381836f, 0.309570f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 767a + {0.693848f, 0.466797f, 0.709473f, 0.481445f, -0.3125f, -29.1250f, 30.0000f, 32, 30}, // 767b + {0.626465f, 0.294434f, 0.642090f, 0.309570f, -0.5000f, -28.9375f, 30.0000f, 32, 31}, // 767c + {0.260254f, 0.759766f, 0.271484f, 0.775391f, 3.9375f, -29.0625f, 30.0000f, 23, 32}, // 767d + {0.224609f, 0.675293f, 0.238770f, 0.689941f, 0.9375f, -27.4375f, 30.0000f, 29, 30}, // 767e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 767f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7680 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7681 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7682 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7683 - {0.485352f, 0.648926f, 0.499023f, 0.664063f, 1.0625f, -29.1875f, 30.0000f, 28, 31}, // 7684 + {0.649414f, 0.683594f, 0.663086f, 0.698730f, 1.0625f, -29.1875f, 30.0000f, 28, 31}, // 7684 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7685 - {0.478027f, 0.383789f, 0.493164f, 0.398926f, -0.1250f, -29.1250f, 30.0000f, 31, 31}, // 7686 - {0.593750f, 0.523926f, 0.608398f, 0.539063f, 0.3750f, -29.3750f, 30.0000f, 30, 31}, // 7687 + {0.189453f, 0.408691f, 0.204590f, 0.423828f, -0.1250f, -29.1250f, 30.0000f, 31, 31}, // 7686 + {0.483398f, 0.549805f, 0.498047f, 0.564941f, 0.3750f, -29.3750f, 30.0000f, 30, 31}, // 7687 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7688 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7689 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 768a @@ -11536,7 +11837,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ad - {0.849121f, 0.272461f, 0.864258f, 0.288086f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 76ae + {0.707520f, 0.294434f, 0.722656f, 0.310059f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 76ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76b1 @@ -11553,18 +11854,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76be - {0.354004f, 0.693359f, 0.369141f, 0.705566f, 0.0625f, -25.5000f, 30.0000f, 31, 25}, // 76bf + {0.121582f, 0.735352f, 0.136719f, 0.747559f, 0.0625f, -25.5000f, 30.0000f, 31, 25}, // 76bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c5 - {0.075684f, 0.616211f, 0.090820f, 0.630371f, -0.5625f, -27.8750f, 30.0000f, 31, 29}, // 76c6 + {0.470703f, 0.643066f, 0.485840f, 0.657227f, -0.5625f, -27.8750f, 30.0000f, 31, 29}, // 76c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76c9 - {0.920410f, 0.444824f, 0.936035f, 0.459473f, -0.6875f, -29.2500f, 30.0000f, 32, 30}, // 76ca + {0.599609f, 0.467285f, 0.615234f, 0.481934f, -0.6875f, -29.2500f, 30.0000f, 32, 30}, // 76ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76cd @@ -11576,21 +11877,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76d5 - {0.897461f, 0.272461f, 0.913086f, 0.287598f, -0.8125f, -29.4375f, 30.0000f, 32, 31}, // 76d6 - {0.252441f, 0.384277f, 0.267578f, 0.399414f, -0.3125f, -29.2500f, 30.0000f, 31, 31}, // 76d7 - {0.587891f, 0.586914f, 0.602539f, 0.601563f, -0.0625f, -28.9375f, 30.0000f, 30, 30}, // 76d8 + {0.382324f, 0.294922f, 0.397949f, 0.310059f, -0.8125f, -29.4375f, 30.0000f, 32, 31}, // 76d6 + {0.569336f, 0.408691f, 0.584473f, 0.423828f, -0.3125f, -29.2500f, 30.0000f, 31, 31}, // 76d7 + {0.698242f, 0.616699f, 0.712891f, 0.631348f, -0.0625f, -28.9375f, 30.0000f, 30, 30}, // 76d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76da - {0.625000f, 0.523926f, 0.640137f, 0.538574f, -0.5625f, -29.0000f, 30.0000f, 31, 30}, // 76db + {0.529785f, 0.549805f, 0.544922f, 0.564453f, -0.5625f, -29.0000f, 30.0000f, 31, 30}, // 76db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76de - {0.212891f, 0.616211f, 0.228027f, 0.630371f, -0.3125f, -27.6875f, 30.0000f, 31, 29}, // 76df + {0.517090f, 0.643066f, 0.532227f, 0.657227f, -0.3125f, -27.6875f, 30.0000f, 31, 29}, // 76df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e2 - {0.771484f, 0.523926f, 0.786621f, 0.538574f, -0.3750f, -28.8125f, 30.0000f, 31, 30}, // 76e3 - {0.205566f, 0.384766f, 0.220703f, 0.399902f, -0.1875f, -29.2500f, 30.0000f, 31, 31}, // 76e4 + {0.545410f, 0.549805f, 0.560547f, 0.564453f, -0.3750f, -28.8125f, 30.0000f, 31, 30}, // 76e3 + {0.143066f, 0.409180f, 0.158203f, 0.424316f, -0.1875f, -29.2500f, 30.0000f, 31, 31}, // 76e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76e7 @@ -11600,26 +11901,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ed - {0.650391f, 0.773438f, 0.660645f, 0.787598f, 4.1875f, -27.1250f, 30.0000f, 21, 29}, // 76ee + {0.277832f, 0.843262f, 0.288086f, 0.857422f, 4.1875f, -27.1250f, 30.0000f, 21, 29}, // 76ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f1 - {0.221191f, 0.384766f, 0.236328f, 0.399902f, -0.1250f, -28.8125f, 30.0000f, 31, 31}, // 76f2 + {0.584961f, 0.409180f, 0.600098f, 0.424316f, -0.1250f, -28.8125f, 30.0000f, 31, 31}, // 76f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f3 - {0.955566f, 0.444824f, 0.970215f, 0.460449f, 0.8125f, -29.0625f, 30.0000f, 30, 32}, // 76f4 + {0.094238f, 0.467285f, 0.108887f, 0.482910f, 0.8125f, -29.0625f, 30.0000f, 30, 32}, // 76f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f7 - {0.853516f, 0.523926f, 0.868164f, 0.539063f, -0.7500f, -28.8750f, 30.0000f, 30, 31}, // 76f8 + {0.607910f, 0.549805f, 0.622559f, 0.564941f, -0.7500f, -28.8750f, 30.0000f, 30, 31}, // 76f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76fd - {0.970703f, 0.444824f, 0.985352f, 0.460449f, 0.0000f, -29.0625f, 30.0000f, 30, 32}, // 76fe + {0.360840f, 0.467773f, 0.375488f, 0.483398f, 0.0000f, -29.0625f, 30.0000f, 30, 32}, // 76fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 76ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7700 - {0.913574f, 0.272461f, 0.928711f, 0.288086f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 7701 + {0.659180f, 0.295410f, 0.674316f, 0.311035f, -0.4375f, -28.9375f, 30.0000f, 31, 32}, // 7701 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7702 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7703 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7704 @@ -11629,8 +11930,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7708 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7709 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 770a - {0.934570f, 0.523926f, 0.949219f, 0.539063f, 0.1250f, -28.5625f, 30.0000f, 30, 31}, // 770b - {0.092285f, 0.524414f, 0.107422f, 0.539063f, 0.1875f, -28.0000f, 30.0000f, 31, 30}, // 770c + {0.137695f, 0.550293f, 0.152344f, 0.565430f, 0.1250f, -28.5625f, 30.0000f, 30, 31}, // 770b + {0.739746f, 0.550781f, 0.754883f, 0.565430f, 0.1875f, -28.0000f, 30.0000f, 31, 30}, // 770c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 770d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 770e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 770f @@ -11649,8 +11950,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 771c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 771d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 771e - {0.929199f, 0.272461f, 0.944336f, 0.288086f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 771f - {0.618652f, 0.586914f, 0.633301f, 0.601563f, 0.9375f, -27.5625f, 30.0000f, 30, 30}, // 7720 + {0.333496f, 0.295898f, 0.348633f, 0.311523f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 771f + {0.257813f, 0.617188f, 0.272461f, 0.631836f, 0.9375f, -27.5625f, 30.0000f, 30, 30}, // 7720 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7721 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7722 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7723 @@ -11676,13 +11977,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7737 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7738 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7739 - {0.949707f, 0.523926f, 0.964355f, 0.539063f, 1.1250f, -28.8750f, 30.0000f, 30, 31}, // 773a + {0.229980f, 0.552246f, 0.244629f, 0.567383f, 1.1250f, -28.8750f, 30.0000f, 30, 31}, // 773a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 773b - {0.122559f, 0.524414f, 0.137695f, 0.539063f, 0.8750f, -27.8125f, 30.0000f, 31, 30}, // 773c + {0.245117f, 0.552246f, 0.260254f, 0.566895f, 0.8750f, -27.8125f, 30.0000f, 31, 30}, // 773c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 773d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 773e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 773f - {0.944824f, 0.272461f, 0.959961f, 0.288086f, -0.8750f, -29.1875f, 30.0000f, 31, 32}, // 7740 + {0.773926f, 0.296387f, 0.789063f, 0.312012f, -0.8750f, -29.1875f, 30.0000f, 31, 32}, // 7740 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7741 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7742 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7743 @@ -11715,9 +12016,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 775e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 775f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7760 - {0.713379f, 0.586914f, 0.728027f, 0.601563f, 0.5625f, -29.0625f, 30.0000f, 30, 30}, // 7761 + {0.680664f, 0.617188f, 0.695313f, 0.631836f, 0.5625f, -29.0625f, 30.0000f, 30, 30}, // 7761 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7762 - {0.602051f, 0.112793f, 0.617676f, 0.128418f, -0.3125f, -29.0625f, 30.0000f, 32, 32}, // 7763 + {0.891602f, 0.130859f, 0.907227f, 0.146484f, -0.3125f, -29.0625f, 30.0000f, 32, 32}, // 7763 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7764 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7765 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7766 @@ -11790,7 +12091,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ab - {0.886719f, 0.524414f, 0.901367f, 0.539551f, 0.8125f, -28.9375f, 30.0000f, 30, 31}, // 77ac + {0.706543f, 0.553223f, 0.721191f, 0.568359f, 0.8125f, -28.9375f, 30.0000f, 30, 31}, // 77ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77af @@ -11837,17 +12138,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77da - {0.121094f, 0.587402f, 0.135742f, 0.602051f, 0.4375f, -27.8125f, 30.0000f, 30, 30}, // 77db + {0.000000f, 0.617676f, 0.014648f, 0.632324f, 0.4375f, -27.8125f, 30.0000f, 30, 30}, // 77db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e1 - {0.397949f, 0.384766f, 0.413086f, 0.399902f, 0.0000f, -28.8750f, 30.0000f, 31, 31}, // 77e2 + {0.078125f, 0.409668f, 0.093262f, 0.424805f, 0.0000f, -28.8750f, 30.0000f, 31, 31}, // 77e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e4 - {0.140625f, 0.445313f, 0.155273f, 0.460938f, 0.0000f, -29.1875f, 30.0000f, 30, 32}, // 77e5 + {0.632813f, 0.467773f, 0.647461f, 0.483398f, 0.0000f, -29.1875f, 30.0000f, 30, 32}, // 77e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77e8 @@ -11855,13 +12156,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ec - {0.446289f, 0.384766f, 0.461426f, 0.399902f, -0.5000f, -28.3125f, 30.0000f, 31, 31}, // 77ed + {0.600586f, 0.409668f, 0.615723f, 0.424805f, -0.5000f, -28.3125f, 30.0000f, 31, 31}, // 77ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ee - {0.960449f, 0.272461f, 0.976074f, 0.287598f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 77ef + {0.789551f, 0.296387f, 0.805176f, 0.311523f, -1.0625f, -28.8125f, 30.0000f, 32, 31}, // 77ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f2 - {0.922363f, 0.587402f, 0.937012f, 0.602051f, 0.0000f, -27.0625f, 30.0000f, 30, 30}, // 77f3 + {0.165527f, 0.617676f, 0.180176f, 0.632324f, 0.0000f, -27.0625f, 30.0000f, 30, 30}, // 77f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77f6 @@ -11875,8 +12176,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 77ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7800 - {0.289063f, 0.616211f, 0.304199f, 0.630371f, -0.8750f, -27.0625f, 30.0000f, 31, 29}, // 7801 - {0.561035f, 0.177246f, 0.577148f, 0.192383f, -0.8750f, -28.7500f, 30.0000f, 33, 31}, // 7802 + {0.595703f, 0.643066f, 0.610840f, 0.657227f, -0.8750f, -27.0625f, 30.0000f, 31, 29}, // 7801 + {0.418945f, 0.196777f, 0.435059f, 0.211914f, -0.8750f, -28.7500f, 30.0000f, 33, 31}, // 7802 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7803 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7804 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7805 @@ -11894,8 +12195,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7811 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7812 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7813 - {0.187500f, 0.445313f, 0.203125f, 0.459961f, -0.9375f, -27.4375f, 30.0000f, 32, 30}, // 7814 - {0.618164f, 0.112793f, 0.633789f, 0.128418f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 7815 + {0.314453f, 0.468750f, 0.330078f, 0.483398f, -0.9375f, -27.4375f, 30.0000f, 32, 30}, // 7814 + {0.393066f, 0.132324f, 0.408691f, 0.147949f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 7815 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7816 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7817 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7818 @@ -11924,9 +12225,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 782f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7830 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7831 - {0.408203f, 0.445313f, 0.423828f, 0.459961f, -1.0000f, -29.0625f, 30.0000f, 32, 30}, // 7832 + {0.777344f, 0.468750f, 0.792969f, 0.483398f, -1.0000f, -29.0625f, 30.0000f, 32, 30}, // 7832 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7833 - {0.634277f, 0.112793f, 0.649902f, 0.128418f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 7834 + {0.451660f, 0.132324f, 0.467285f, 0.147949f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 7834 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7835 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7836 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7837 @@ -11967,7 +12268,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 785a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 785b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 785c - {0.976563f, 0.272461f, 0.991699f, 0.288086f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 785d + {0.192871f, 0.297363f, 0.208008f, 0.312988f, -0.5625f, -29.0000f, 30.0000f, 31, 32}, // 785d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 785e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 785f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7860 @@ -11981,10 +12282,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7868 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7869 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 786a - {0.309570f, 0.017578f, 0.325684f, 0.033203f, -1.2500f, -28.9375f, 30.0000f, 33, 32}, // 786b - {0.424316f, 0.445313f, 0.439941f, 0.459961f, -0.6875f, -27.5625f, 30.0000f, 32, 30}, // 786c + {0.259277f, 0.041992f, 0.275391f, 0.057617f, -1.2500f, -28.9375f, 30.0000f, 33, 32}, // 786b + {0.793457f, 0.468750f, 0.809082f, 0.483398f, -0.6875f, -27.5625f, 30.0000f, 32, 30}, // 786c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 786d - {0.458984f, 0.445313f, 0.473633f, 0.460938f, -0.5000f, -29.5625f, 30.0000f, 30, 32}, // 786e + {0.032227f, 0.470215f, 0.046875f, 0.485840f, -0.5000f, -29.5625f, 30.0000f, 30, 32}, // 786e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 786f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7870 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7871 @@ -12003,7 +12304,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 787e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 787f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7880 - {0.577637f, 0.177246f, 0.593750f, 0.192383f, -1.2500f, -29.3125f, 30.0000f, 33, 31}, // 7881 + {0.435547f, 0.196777f, 0.451660f, 0.211914f, -1.2500f, -29.3125f, 30.0000f, 33, 31}, // 7881 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7882 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7883 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7884 @@ -12019,7 +12320,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 788e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 788f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7890 - {0.650391f, 0.112793f, 0.666016f, 0.128418f, -1.1250f, -29.3750f, 30.0000f, 32, 32}, // 7891 + {0.467773f, 0.132324f, 0.483398f, 0.147949f, -1.1250f, -29.3750f, 30.0000f, 32, 32}, // 7891 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7892 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7893 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7894 @@ -12041,7 +12342,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78a6 - {0.270996f, 0.272949f, 0.286133f, 0.288574f, -0.2500f, -29.3750f, 30.0000f, 31, 32}, // 78a7 + {0.512207f, 0.297363f, 0.527344f, 0.312988f, -0.2500f, -29.3750f, 30.0000f, 31, 32}, // 78a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78aa @@ -12060,14 +12361,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78b9 - {0.730469f, 0.112793f, 0.746094f, 0.128418f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 78ba + {0.483887f, 0.132324f, 0.499512f, 0.147949f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 78ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78bb - {0.964844f, 0.524414f, 0.979980f, 0.539063f, -0.5000f, -27.4375f, 30.0000f, 31, 30}, // 78bc + {0.403809f, 0.553711f, 0.418945f, 0.568359f, -0.5000f, -27.4375f, 30.0000f, 31, 30}, // 78bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78c0 - {0.286621f, 0.272949f, 0.302246f, 0.288086f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 78c1 + {0.208496f, 0.297852f, 0.224121f, 0.312988f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 78c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78c4 @@ -12106,7 +12407,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78e7 - {0.464355f, 0.272949f, 0.479980f, 0.288086f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 78e8 + {0.527832f, 0.297852f, 0.543457f, 0.312988f, -0.9375f, -29.0000f, 30.0000f, 32, 31}, // 78e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78eb @@ -12131,7 +12432,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 78ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7900 - {0.746582f, 0.112793f, 0.762207f, 0.128418f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 7901 + {0.500000f, 0.132324f, 0.515625f, 0.147949f, -0.6875f, -29.2500f, 30.0000f, 32, 32}, // 7901 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7902 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7903 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7904 @@ -12144,7 +12445,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 790b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 790c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 790d - {0.512207f, 0.272949f, 0.527832f, 0.288086f, -0.9375f, -28.8125f, 30.0000f, 32, 31}, // 790e + {0.642578f, 0.297852f, 0.658203f, 0.312988f, -0.9375f, -28.8125f, 30.0000f, 32, 31}, // 790e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 790f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7910 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7911 @@ -12188,11 +12489,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7937 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7938 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7939 - {0.770996f, 0.646973f, 0.785645f, 0.661133f, 0.6875f, -26.6875f, 30.0000f, 30, 29}, // 793a + {0.710449f, 0.675781f, 0.725098f, 0.689941f, 0.6875f, -26.6875f, 30.0000f, 30, 29}, // 793a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 793b - {0.625977f, 0.272949f, 0.641602f, 0.288086f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 793c + {0.690430f, 0.297852f, 0.706055f, 0.312988f, -0.7500f, -28.6250f, 30.0000f, 32, 31}, // 793c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 793d - {0.831055f, 0.272949f, 0.846680f, 0.288086f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 793e + {0.560547f, 0.298340f, 0.576172f, 0.313477f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 793e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 793f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7940 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7941 @@ -12202,8 +12503,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7945 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7946 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7947 - {0.762695f, 0.112793f, 0.778320f, 0.128418f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 7948 - {0.240234f, 0.273438f, 0.255859f, 0.288574f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 7949 + {0.582520f, 0.132324f, 0.598145f, 0.147949f, -0.6250f, -29.0625f, 30.0000f, 32, 32}, // 7948 + {0.576660f, 0.298340f, 0.592285f, 0.313477f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 7949 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 794a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 794b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 794c @@ -12216,30 +12517,30 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7953 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7954 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7955 - {0.370605f, 0.273438f, 0.386230f, 0.288574f, -1.0000f, -28.5625f, 30.0000f, 32, 31}, // 7956 + {0.674805f, 0.298340f, 0.690430f, 0.313477f, -1.0000f, -28.5625f, 30.0000f, 32, 31}, // 7956 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7957 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7958 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7959 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 795a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 795b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 795c - {0.657227f, 0.273438f, 0.672852f, 0.288574f, -1.0000f, -28.6875f, 30.0000f, 32, 31}, // 795d - {0.474121f, 0.445313f, 0.488770f, 0.460938f, -0.3750f, -29.1250f, 30.0000f, 30, 32}, // 795e + {0.047852f, 0.299316f, 0.063477f, 0.314453f, -1.0000f, -28.6875f, 30.0000f, 32, 31}, // 795d + {0.047363f, 0.470215f, 0.062012f, 0.485840f, -0.3750f, -29.1250f, 30.0000f, 30, 32}, // 795e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 795f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7960 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7961 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7962 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7963 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7964 - {0.778809f, 0.112793f, 0.794434f, 0.128418f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 7965 + {0.932129f, 0.132324f, 0.947754f, 0.147949f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 7965 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7966 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7967 - {0.980469f, 0.524414f, 0.995605f, 0.539063f, 0.1875f, -27.6875f, 30.0000f, 31, 30}, // 7968 + {0.576172f, 0.553711f, 0.591309f, 0.568359f, 0.1875f, -27.6875f, 30.0000f, 31, 30}, // 7968 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7969 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 796a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 796b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 796c - {0.794922f, 0.112793f, 0.810547f, 0.128418f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 796d + {0.948242f, 0.132324f, 0.963867f, 0.147949f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 796d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 796e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 796f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7970 @@ -12259,11 +12560,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 797e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 797f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7980 - {0.192383f, 0.274414f, 0.208008f, 0.289551f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 7981 + {0.079590f, 0.299316f, 0.095215f, 0.314453f, -0.6250f, -29.0625f, 30.0000f, 32, 31}, // 7981 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7982 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7983 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7984 - {0.811035f, 0.112793f, 0.826660f, 0.128418f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7985 + {0.964355f, 0.132324f, 0.979980f, 0.147949f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7985 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7986 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7987 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7988 @@ -12271,9 +12572,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 798a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 798b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 798c - {0.461914f, 0.384766f, 0.477051f, 0.399902f, -0.9375f, -29.0625f, 30.0000f, 31, 31}, // 798d + {0.062500f, 0.410156f, 0.077637f, 0.425293f, -0.9375f, -29.0625f, 30.0000f, 31, 31}, // 798d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 798e - {0.827148f, 0.112793f, 0.842773f, 0.128418f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 798f + {0.980469f, 0.132324f, 0.996094f, 0.147949f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 798f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7990 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7991 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7992 @@ -12322,8 +12623,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79bf - {0.418457f, 0.274414f, 0.434082f, 0.289551f, -0.5000f, -28.9375f, 30.0000f, 32, 31}, // 79c0 - {0.872559f, 0.112793f, 0.888184f, 0.128418f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 79c1 + {0.592773f, 0.299316f, 0.608398f, 0.314453f, -0.5000f, -28.9375f, 30.0000f, 32, 31}, // 79c0 + {0.873047f, 0.132813f, 0.888672f, 0.148438f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 79c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79c4 @@ -12333,27 +12634,27 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ca - {0.888672f, 0.112793f, 0.904297f, 0.128418f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 79cb + {0.907715f, 0.133301f, 0.923340f, 0.148926f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 79cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d0 - {0.480469f, 0.274414f, 0.496094f, 0.289551f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d1 - {0.224609f, 0.274902f, 0.240234f, 0.290039f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d2 + {0.608887f, 0.299316f, 0.624512f, 0.314453f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d1 + {0.063965f, 0.299805f, 0.079590f, 0.314941f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d7 - {0.208496f, 0.275391f, 0.224121f, 0.290527f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d8 + {0.144531f, 0.299805f, 0.160156f, 0.314941f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 79d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79de - {0.338867f, 0.276855f, 0.354492f, 0.291992f, -1.0625f, -28.5625f, 30.0000f, 32, 31}, // 79df + {0.160645f, 0.299805f, 0.176270f, 0.314941f, -1.0625f, -28.5625f, 30.0000f, 32, 31}, // 79df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e2 @@ -12363,14 +12664,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79e8 - {0.326172f, 0.017578f, 0.342285f, 0.033203f, -0.9375f, -29.1875f, 30.0000f, 33, 32}, // 79e9 + {0.275879f, 0.041992f, 0.291992f, 0.057617f, -0.9375f, -29.1875f, 30.0000f, 33, 32}, // 79e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79ef - {0.386719f, 0.279785f, 0.402344f, 0.294922f, -0.6875f, -29.1250f, 30.0000f, 32, 31}, // 79f0 + {0.111816f, 0.300293f, 0.127441f, 0.315430f, -0.6875f, -29.1250f, 30.0000f, 32, 31}, // 79f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79f3 @@ -12381,7 +12682,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79fa - {0.112305f, 0.280273f, 0.127441f, 0.295898f, -0.5625f, -29.1875f, 30.0000f, 31, 32}, // 79fb + {0.127930f, 0.300293f, 0.143066f, 0.315918f, -0.5625f, -29.1875f, 30.0000f, 31, 32}, // 79fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 79fe @@ -12397,10 +12698,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a0a - {0.402832f, 0.280273f, 0.418457f, 0.295410f, -1.1875f, -28.5000f, 30.0000f, 32, 31}, // 7a0b + {0.176758f, 0.300293f, 0.192383f, 0.315430f, -1.1875f, -28.5000f, 30.0000f, 32, 31}, // 7a0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a0c - {0.302734f, 0.280762f, 0.317871f, 0.296387f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 7a0d - {0.904785f, 0.112793f, 0.920410f, 0.128418f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7a0e + {0.016113f, 0.300781f, 0.031250f, 0.316406f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 7a0d + {0.096680f, 0.134277f, 0.112305f, 0.149902f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7a0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a11 @@ -12412,7 +12713,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a19 - {0.920898f, 0.112793f, 0.936523f, 0.128418f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 7a1a + {0.112793f, 0.134277f, 0.128418f, 0.149902f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 7a1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a1d @@ -12432,12 +12733,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a2d - {0.937012f, 0.112793f, 0.952637f, 0.128418f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 7a2e + {0.128906f, 0.134766f, 0.144531f, 0.150391f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 7a2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a31 - {0.000000f, 0.281738f, 0.015625f, 0.296875f, -1.0625f, -28.7500f, 30.0000f, 32, 31}, // 7a32 - {0.016113f, 0.282715f, 0.031738f, 0.297852f, -1.4375f, -29.0625f, 30.0000f, 32, 31}, // 7a33 + {0.000000f, 0.301758f, 0.015625f, 0.316895f, -1.0625f, -28.7500f, 30.0000f, 32, 31}, // 7a32 + {0.741699f, 0.301758f, 0.757324f, 0.316895f, -1.4375f, -29.0625f, 30.0000f, 32, 31}, // 7a33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a36 @@ -12446,13 +12747,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a3b - {0.342773f, 0.017578f, 0.358887f, 0.033203f, -0.8750f, -29.0000f, 30.0000f, 33, 32}, // 7a3c + {0.582031f, 0.041992f, 0.598145f, 0.057617f, -0.8750f, -29.0000f, 30.0000f, 33, 32}, // 7a3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a3e - {0.032227f, 0.283691f, 0.047363f, 0.299316f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 7a3f - {0.953125f, 0.112793f, 0.968750f, 0.128418f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 7a40 + {0.723145f, 0.302246f, 0.738281f, 0.317871f, -0.3750f, -29.0000f, 30.0000f, 31, 32}, // 7a3f + {0.763184f, 0.134766f, 0.778809f, 0.150391f, -0.6875f, -28.8125f, 30.0000f, 32, 32}, // 7a40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a41 - {0.594238f, 0.177246f, 0.610352f, 0.192383f, -0.8125f, -28.8125f, 30.0000f, 33, 31}, // 7a42 + {0.452148f, 0.196777f, 0.468262f, 0.211914f, -0.8125f, -28.8125f, 30.0000f, 33, 31}, // 7a42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a45 @@ -12463,9 +12764,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a4c - {0.969238f, 0.112793f, 0.984863f, 0.128418f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 7a4d + {0.409180f, 0.135254f, 0.424805f, 0.150879f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 7a4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a4e - {0.063965f, 0.283691f, 0.079590f, 0.298828f, -1.0625f, -29.1875f, 30.0000f, 32, 31}, // 7a4f + {0.224609f, 0.302734f, 0.240234f, 0.317871f, -1.0625f, -29.1875f, 30.0000f, 32, 31}, // 7a4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a52 @@ -12491,9 +12792,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a68 - {0.080078f, 0.283691f, 0.095703f, 0.298828f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 7a69 + {0.240723f, 0.302734f, 0.256348f, 0.317871f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 7a69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a6a - {0.610840f, 0.177246f, 0.626953f, 0.192383f, -1.2500f, -29.2500f, 30.0000f, 33, 31}, // 7a6b + {0.562988f, 0.196777f, 0.579102f, 0.211914f, -1.2500f, -29.2500f, 30.0000f, 33, 31}, // 7a6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a6e @@ -12502,22 +12803,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a73 - {0.301758f, 0.387207f, 0.316895f, 0.402344f, -0.0625f, -28.6875f, 30.0000f, 31, 31}, // 7a74 + {0.110840f, 0.410156f, 0.125977f, 0.425293f, -0.0625f, -28.6875f, 30.0000f, 31, 31}, // 7a74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a75 - {0.047852f, 0.284180f, 0.063477f, 0.299316f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 7a76 + {0.285156f, 0.302734f, 0.300781f, 0.317871f, -0.5625f, -28.6875f, 30.0000f, 32, 31}, // 7a76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a79 - {0.816895f, 0.646973f, 0.831055f, 0.661621f, 0.5625f, -29.0625f, 30.0000f, 29, 30}, // 7a7a + {0.146973f, 0.676270f, 0.161133f, 0.690918f, 0.5625f, -29.0625f, 30.0000f, 29, 30}, // 7a7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a80 - {0.364746f, 0.389648f, 0.379883f, 0.404785f, -0.2500f, -28.7500f, 30.0000f, 31, 31}, // 7a81 + {0.158691f, 0.410645f, 0.173828f, 0.425781f, -0.2500f, -28.7500f, 30.0000f, 31, 31}, // 7a81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a82 - {0.246094f, 0.524902f, 0.260742f, 0.540039f, -0.3750f, -28.9375f, 30.0000f, 30, 31}, // 7a83 + {0.691895f, 0.553711f, 0.706543f, 0.568848f, -0.3750f, -28.9375f, 30.0000f, 30, 31}, // 7a83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a86 @@ -12532,12 +12833,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a91 - {0.372559f, 0.524902f, 0.387207f, 0.540039f, 0.2500f, -29.1875f, 30.0000f, 30, 31}, // 7a92 - {0.318359f, 0.285156f, 0.333984f, 0.300293f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 7a93 + {0.000000f, 0.554199f, 0.014648f, 0.569336f, 0.2500f, -29.1875f, 30.0000f, 30, 31}, // 7a92 + {0.301270f, 0.302734f, 0.316895f, 0.317871f, -0.5625f, -29.1875f, 30.0000f, 32, 31}, // 7a93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a96 - {0.577148f, 0.648926f, 0.590820f, 0.664063f, 1.0625f, -28.9375f, 30.0000f, 28, 31}, // 7a97 + {0.830078f, 0.683594f, 0.843750f, 0.698730f, 1.0625f, -28.9375f, 30.0000f, 28, 31}, // 7a97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a9a @@ -12545,7 +12846,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7a9e - {0.858887f, 0.445313f, 0.873535f, 0.460938f, -0.7500f, -29.1250f, 30.0000f, 30, 32}, // 7a9f + {0.487305f, 0.470215f, 0.501953f, 0.485840f, -0.7500f, -29.1250f, 30.0000f, 30, 32}, // 7a9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aa0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aa1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aa2 @@ -12560,8 +12861,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aad - {0.160645f, 0.286133f, 0.175781f, 0.301758f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 7aae - {0.535156f, 0.113281f, 0.550781f, 0.128906f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7aaf + {0.256836f, 0.303223f, 0.271973f, 0.318848f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 7aae + {0.425293f, 0.135254f, 0.440918f, 0.150879f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7aaf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ab0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ab1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ab2 @@ -12589,7 +12890,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ac8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ac9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aca - {0.969238f, 0.662109f, 0.983398f, 0.676270f, 0.8125f, -28.6875f, 30.0000f, 29, 29}, // 7acb + {0.663574f, 0.693359f, 0.677734f, 0.707520f, 0.8125f, -28.6875f, 30.0000f, 29, 29}, // 7acb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7acc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7acd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ace @@ -12603,19 +12904,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ad6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ad7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ad8 - {0.436523f, 0.524902f, 0.451172f, 0.540039f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 7ad9 + {0.214844f, 0.554199f, 0.229492f, 0.569336f, 0.1875f, -29.0000f, 30.0000f, 30, 31}, // 7ad9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ada {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7adb - {0.380371f, 0.390137f, 0.395508f, 0.405273f, -0.0625f, -29.1250f, 30.0000f, 31, 31}, // 7adc + {0.000000f, 0.411133f, 0.015137f, 0.426270f, -0.0625f, -29.1250f, 30.0000f, 31, 31}, // 7adc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7add {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ade {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7adf - {0.109375f, 0.390625f, 0.124512f, 0.405762f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 7ae0 + {0.015625f, 0.411133f, 0.030762f, 0.426270f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 7ae0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae4 - {0.937500f, 0.587402f, 0.952148f, 0.602051f, 0.0625f, -29.0000f, 30.0000f, 30, 30}, // 7ae5 + {0.713379f, 0.617676f, 0.728027f, 0.632324f, 0.0625f, -29.0000f, 30.0000f, 30, 30}, // 7ae5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ae8 @@ -12625,17 +12926,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7aee - {0.666504f, 0.113281f, 0.682129f, 0.128906f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 7aef + {0.665527f, 0.135254f, 0.681152f, 0.150879f, -0.7500f, -28.9375f, 30.0000f, 32, 32}, // 7aef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af5 - {0.843262f, 0.113281f, 0.858887f, 0.128906f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 7af6 + {0.369629f, 0.136719f, 0.385254f, 0.152344f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 7af6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7af8 - {0.551270f, 0.113770f, 0.566895f, 0.129395f, -0.5625f, -29.5000f, 30.0000f, 32, 32}, // 7af9 + {0.707520f, 0.136719f, 0.723145f, 0.152344f, -0.5625f, -29.5000f, 30.0000f, 32, 32}, // 7af9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7afa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7afb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7afc @@ -12659,7 +12960,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b10 - {0.354980f, 0.286133f, 0.370117f, 0.301758f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7b11 + {0.450684f, 0.303711f, 0.465820f, 0.319336f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7b11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b14 @@ -12669,7 +12970,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b1a - {0.273926f, 0.114258f, 0.289551f, 0.129883f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 7b1b + {0.834473f, 0.136719f, 0.850098f, 0.152344f, -0.5625f, -29.2500f, 30.0000f, 32, 32}, // 7b1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b1e @@ -12680,13 +12981,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b25 - {0.290039f, 0.114258f, 0.305664f, 0.129883f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 7b26 + {0.850586f, 0.137207f, 0.866211f, 0.152832f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 7b26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b2b - {0.000000f, 0.391602f, 0.015137f, 0.406738f, -0.1875f, -29.0625f, 30.0000f, 31, 31}, // 7b2c + {0.126465f, 0.411133f, 0.141602f, 0.426270f, -0.1875f, -29.0625f, 30.0000f, 31, 31}, // 7b2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b2f @@ -12712,23 +13013,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b45 - {0.096191f, 0.286621f, 0.111328f, 0.302246f, 0.1875f, -29.1875f, 30.0000f, 31, 32}, // 7b46 + {0.031738f, 0.304199f, 0.046875f, 0.319824f, 0.1875f, -29.1875f, 30.0000f, 31, 32}, // 7b46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b48 - {0.127930f, 0.286621f, 0.143066f, 0.302246f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7b49 + {0.466309f, 0.304199f, 0.481445f, 0.319824f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7b49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b4a - {0.176270f, 0.286621f, 0.191406f, 0.302246f, -0.5625f, -29.4375f, 30.0000f, 31, 32}, // 7b4b + {0.481934f, 0.304199f, 0.497070f, 0.319824f, -0.5625f, -29.4375f, 30.0000f, 31, 32}, // 7b4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b51 - {0.306152f, 0.114258f, 0.321777f, 0.129883f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 7b52 + {0.209473f, 0.138672f, 0.225098f, 0.154297f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 7b52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b53 - {0.520508f, 0.017578f, 0.536621f, 0.033203f, -1.0625f, -29.3125f, 30.0000f, 33, 32}, // 7b54 + {0.598633f, 0.041992f, 0.614746f, 0.057617f, -1.0625f, -29.3125f, 30.0000f, 33, 32}, // 7b54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b55 - {0.476074f, 0.114258f, 0.491699f, 0.129883f, -0.6250f, -29.3750f, 30.0000f, 32, 32}, // 7b56 + {0.225586f, 0.138672f, 0.241211f, 0.154297f, -0.6250f, -29.3750f, 30.0000f, 32, 32}, // 7b56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b59 @@ -12770,14 +13071,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b7f - {0.015625f, 0.393066f, 0.030762f, 0.408203f, -0.6250f, -29.0000f, 30.0000f, 31, 31}, // 7b80 + {0.734375f, 0.412109f, 0.749512f, 0.427246f, -0.6250f, -29.0000f, 30.0000f, 31, 31}, // 7b80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b86 - {0.492188f, 0.114258f, 0.507813f, 0.129883f, -0.8125f, -29.4375f, 30.0000f, 32, 32}, // 7b87 + {0.241699f, 0.138672f, 0.257324f, 0.154297f, -0.8125f, -29.4375f, 30.0000f, 32, 32}, // 7b87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b8a @@ -12793,7 +13094,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b96 - {0.561035f, 0.286621f, 0.576172f, 0.302246f, -0.5625f, -29.2500f, 30.0000f, 31, 32}, // 7b97 + {0.757813f, 0.304199f, 0.772949f, 0.319824f, -0.5625f, -29.2500f, 30.0000f, 31, 32}, // 7b97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b9a @@ -12803,7 +13104,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7b9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ba0 - {0.642090f, 0.286621f, 0.657227f, 0.302246f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 7ba1 + {0.317383f, 0.305176f, 0.332520f, 0.320801f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 7ba1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ba2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ba3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ba4 @@ -12819,7 +13120,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7baf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bb0 - {0.459473f, 0.114746f, 0.475098f, 0.130371f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7bb1 + {0.548828f, 0.138672f, 0.564453f, 0.154297f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7bb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bb4 @@ -12834,16 +13135,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bbf - {0.864746f, 0.286621f, 0.879883f, 0.302246f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 7bc0 + {0.834961f, 0.305176f, 0.850098f, 0.320801f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 7bc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc3 - {0.528320f, 0.287109f, 0.543457f, 0.302734f, 0.0000f, -29.2500f, 30.0000f, 31, 32}, // 7bc4 + {0.349121f, 0.306641f, 0.364258f, 0.322266f, 0.0000f, -29.2500f, 30.0000f, 31, 32}, // 7bc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bc8 - {0.700684f, 0.114746f, 0.716309f, 0.130371f, -0.4375f, -29.1875f, 30.0000f, 32, 32}, // 7bc9 + {0.564941f, 0.138672f, 0.580566f, 0.154297f, -0.4375f, -29.1875f, 30.0000f, 32, 32}, // 7bc9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bcb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7bcc @@ -12870,7 +13171,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be3 - {0.593750f, 0.287109f, 0.608887f, 0.302734f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 7be4 + {0.398438f, 0.306641f, 0.413574f, 0.322266f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 7be4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7be7 @@ -12931,7 +13232,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c20 - {0.508301f, 0.115723f, 0.523926f, 0.131348f, -1.2500f, -29.3750f, 30.0000f, 32, 32}, // 7c21 + {0.681641f, 0.139160f, 0.697266f, 0.154785f, -1.2500f, -29.3750f, 30.0000f, 32, 32}, // 7c21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c24 @@ -12961,7 +13262,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c3e - {0.209473f, 0.116211f, 0.225098f, 0.131836f, -0.6875f, -29.6250f, 30.0000f, 32, 32}, // 7c3f + {0.723633f, 0.139160f, 0.739258f, 0.154785f, -0.6875f, -29.6250f, 30.0000f, 32, 32}, // 7c3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c42 @@ -12975,7 +13276,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c4c - {0.225586f, 0.116211f, 0.241211f, 0.131836f, -1.0625f, -29.6250f, 30.0000f, 32, 32}, // 7c4d + {0.739746f, 0.139160f, 0.755371f, 0.154785f, -1.0625f, -29.6250f, 30.0000f, 32, 32}, // 7c4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c50 @@ -13013,7 +13314,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c72 - {0.046875f, 0.393555f, 0.062012f, 0.408691f, -0.3125f, -28.9375f, 30.0000f, 31, 31}, // 7c73 + {0.222168f, 0.412598f, 0.237305f, 0.427734f, -0.3125f, -28.9375f, 30.0000f, 31, 31}, // 7c73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c76 @@ -13035,25 +13336,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c88 - {0.627441f, 0.177246f, 0.643555f, 0.192383f, -1.1875f, -28.8750f, 30.0000f, 33, 31}, // 7c89 + {0.908203f, 0.196777f, 0.924316f, 0.211914f, -1.1875f, -28.8750f, 30.0000f, 33, 31}, // 7c89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c8a - {0.814453f, 0.287109f, 0.830078f, 0.302246f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 7c8b + {0.867188f, 0.306641f, 0.882813f, 0.321777f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 7c8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c91 - {0.241699f, 0.116211f, 0.257324f, 0.131836f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 7c92 + {0.598633f, 0.139648f, 0.614258f, 0.155273f, -0.9375f, -29.1250f, 30.0000f, 32, 32}, // 7c92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c96 - {0.880371f, 0.287109f, 0.895996f, 0.302246f, -0.6250f, -29.0000f, 30.0000f, 32, 31}, // 7c97 - {0.576660f, 0.287598f, 0.591797f, 0.303223f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 7c98 + {0.946777f, 0.306641f, 0.962402f, 0.321777f, -0.6250f, -29.0000f, 30.0000f, 32, 31}, // 7c97 + {0.414063f, 0.307129f, 0.429199f, 0.322754f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 7c98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c9a - {0.062500f, 0.394043f, 0.077637f, 0.409180f, -0.5000f, -29.0625f, 30.0000f, 31, 31}, // 7c9b + {0.253906f, 0.412598f, 0.269043f, 0.427734f, -0.5000f, -29.0625f, 30.0000f, 31, 31}, // 7c9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7c9e @@ -13065,7 +13366,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ca4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ca5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ca6 - {0.609375f, 0.287598f, 0.625000f, 0.302734f, -1.0000f, -28.8750f, 30.0000f, 32, 31}, // 7ca7 + {0.429688f, 0.307129f, 0.445313f, 0.322266f, -1.0000f, -28.8750f, 30.0000f, 32, 31}, // 7ca7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ca8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ca9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7caa @@ -13088,7 +13389,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cbd - {0.257813f, 0.116211f, 0.273438f, 0.131836f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 7cbe + {0.614746f, 0.139648f, 0.630371f, 0.155273f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 7cbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cc1 @@ -13112,7 +13413,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd5 - {0.673340f, 0.287598f, 0.688965f, 0.302734f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 7cd6 + {0.543945f, 0.307129f, 0.559570f, 0.322266f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 7cd6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cd9 @@ -13129,7 +13430,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ce4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ce5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ce6 - {0.722168f, 0.287598f, 0.737793f, 0.302734f, -0.8125f, -28.5625f, 30.0000f, 32, 31}, // 7ce7 + {0.905762f, 0.307617f, 0.921387f, 0.322754f, -0.8125f, -28.5625f, 30.0000f, 32, 31}, // 7ce7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ce8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ce9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cea @@ -13146,49 +13447,49 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cf7 - {0.143555f, 0.288086f, 0.158691f, 0.303711f, -0.3750f, -29.4375f, 30.0000f, 31, 32}, // 7cf8 + {0.805664f, 0.308105f, 0.820801f, 0.323730f, -0.3750f, -29.4375f, 30.0000f, 31, 32}, // 7cf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cfa - {0.031250f, 0.394531f, 0.046387f, 0.409668f, -0.1250f, -29.0625f, 30.0000f, 31, 31}, // 7cfb + {0.716309f, 0.412598f, 0.731445f, 0.427734f, -0.1250f, -29.0625f, 30.0000f, 31, 31}, // 7cfb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cfd - {0.434570f, 0.288086f, 0.449707f, 0.303711f, -0.8750f, -29.1875f, 30.0000f, 31, 32}, // 7cfe + {0.850586f, 0.308105f, 0.865723f, 0.323730f, -0.8750f, -29.1875f, 30.0000f, 31, 32}, // 7cfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7cff - {0.366699f, 0.117676f, 0.382324f, 0.133301f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d00 + {0.048340f, 0.140137f, 0.063965f, 0.155762f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d03 - {0.543945f, 0.288086f, 0.559082f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d04 - {0.415527f, 0.120605f, 0.431152f, 0.136230f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7d05 + {0.883301f, 0.308105f, 0.898438f, 0.323730f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d04 + {0.064453f, 0.140137f, 0.080078f, 0.155762f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7d05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d0a - {0.431641f, 0.121094f, 0.447266f, 0.136719f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d0b + {0.080566f, 0.140137f, 0.096191f, 0.155762f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d0c - {0.689453f, 0.288086f, 0.704590f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d0d + {0.921875f, 0.308594f, 0.937012f, 0.324219f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d13 - {0.128906f, 0.122559f, 0.144531f, 0.138184f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d14 + {0.630859f, 0.140625f, 0.646484f, 0.156250f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d18 - {0.145020f, 0.122559f, 0.160645f, 0.138184f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d19 - {0.322266f, 0.123047f, 0.337891f, 0.138672f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d1a - {0.338379f, 0.123047f, 0.354004f, 0.138672f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d1b + {0.646973f, 0.140625f, 0.662598f, 0.156250f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d19 + {0.145020f, 0.141602f, 0.160645f, 0.157227f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d1a + {0.177246f, 0.141602f, 0.192871f, 0.157227f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d1f - {0.284668f, 0.395508f, 0.299805f, 0.410645f, -0.1875f, -29.0625f, 30.0000f, 31, 31}, // 7d20 - {0.000000f, 0.124023f, 0.015625f, 0.139648f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d21 - {0.705078f, 0.288086f, 0.720215f, 0.303711f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 7d22 + {0.269531f, 0.413086f, 0.284668f, 0.428223f, -0.1875f, -29.0625f, 30.0000f, 31, 31}, // 7d20 + {0.193359f, 0.141602f, 0.208984f, 0.157227f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d21 + {0.962891f, 0.308594f, 0.978027f, 0.324219f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 7d22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d25 @@ -13197,22 +13498,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d2a - {0.830078f, 0.395508f, 0.845215f, 0.410645f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 7d2b + {0.237793f, 0.414063f, 0.252930f, 0.429199f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 7d2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d2e - {0.845703f, 0.395508f, 0.860840f, 0.410645f, -0.5000f, -28.2500f, 30.0000f, 31, 31}, // 7d2f - {0.738281f, 0.288086f, 0.753418f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d30 + {0.031250f, 0.414551f, 0.046387f, 0.429688f, -0.5000f, -28.2500f, 30.0000f, 31, 31}, // 7d2f + {0.978516f, 0.308594f, 0.993652f, 0.324219f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d32 - {0.753906f, 0.288086f, 0.769043f, 0.303711f, -0.9375f, -29.1875f, 30.0000f, 31, 32}, // 7d33 + {0.095703f, 0.309082f, 0.110840f, 0.324707f, -0.9375f, -29.1875f, 30.0000f, 31, 32}, // 7d33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d38 - {0.769531f, 0.288086f, 0.784668f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d39 - {0.016113f, 0.124023f, 0.031738f, 0.139648f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d3a + {0.364746f, 0.310059f, 0.379883f, 0.325684f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d39 + {0.161133f, 0.142090f, 0.176758f, 0.157715f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d3d @@ -13220,9 +13521,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d41 - {0.032227f, 0.124023f, 0.047852f, 0.139648f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d42 + {0.000000f, 0.143066f, 0.015625f, 0.158691f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d43 - {0.048340f, 0.125488f, 0.063965f, 0.141113f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 7d44 + {0.016113f, 0.143066f, 0.031738f, 0.158691f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 7d44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d47 @@ -13230,11 +13531,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d4b - {0.064453f, 0.125488f, 0.080078f, 0.141113f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 7d4c + {0.032227f, 0.143066f, 0.047852f, 0.158691f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 7d4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d4f - {0.080566f, 0.125488f, 0.096191f, 0.141113f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d50 + {0.779297f, 0.143555f, 0.794922f, 0.159180f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d53 @@ -13248,15 +13549,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d5d - {0.096680f, 0.125488f, 0.112305f, 0.141113f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7d5e + {0.795410f, 0.143555f, 0.811035f, 0.159180f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7d5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d60 - {0.537109f, 0.017578f, 0.553223f, 0.033203f, -1.0000f, -29.5000f, 30.0000f, 33, 32}, // 7d61 + {0.722168f, 0.042480f, 0.738281f, 0.058105f, -1.0000f, -29.5000f, 30.0000f, 33, 32}, // 7d61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d65 - {0.112793f, 0.127441f, 0.128418f, 0.143066f, -1.0000f, -29.6250f, 30.0000f, 32, 32}, // 7d66 + {0.273926f, 0.144043f, 0.289551f, 0.159668f, -1.0000f, -29.6250f, 30.0000f, 32, 32}, // 7d66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d69 @@ -13267,15 +13568,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d70 - {0.161133f, 0.127930f, 0.176758f, 0.143555f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d71 + {0.290039f, 0.144043f, 0.305664f, 0.159668f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d74 - {0.193359f, 0.127930f, 0.208984f, 0.143555f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d75 - {0.382813f, 0.127930f, 0.398438f, 0.143555f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d76 + {0.306152f, 0.144043f, 0.321777f, 0.159668f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d75 + {0.322266f, 0.144043f, 0.337891f, 0.159668f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 7d76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d78 - {0.936523f, 0.445313f, 0.951172f, 0.460938f, -1.0000f, -29.1875f, 30.0000f, 30, 32}, // 7d79 + {0.140625f, 0.470703f, 0.155273f, 0.486328f, -1.0000f, -29.1875f, 30.0000f, 30, 32}, // 7d79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d7c @@ -13301,14 +13602,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d92 - {0.398926f, 0.127930f, 0.414551f, 0.143555f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 7d93 + {0.338379f, 0.144043f, 0.354004f, 0.159668f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 7d93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d98 - {0.785156f, 0.288086f, 0.800293f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d99 - {0.682617f, 0.127930f, 0.698242f, 0.143555f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d9a + {0.625000f, 0.310059f, 0.640137f, 0.325684f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7d99 + {0.257813f, 0.144531f, 0.273438f, 0.160156f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7d9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7d9d @@ -13327,12 +13628,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7daa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dac - {0.177246f, 0.128418f, 0.192871f, 0.144043f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dad + {0.516113f, 0.145508f, 0.531738f, 0.161133f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7daf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7db0 - {0.896484f, 0.288086f, 0.911621f, 0.303711f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7db1 - {0.960449f, 0.288086f, 0.975586f, 0.303711f, -1.0625f, -29.1875f, 30.0000f, 31, 32}, // 7db2 + {0.380371f, 0.310547f, 0.395508f, 0.326172f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7db1 + {0.706543f, 0.310547f, 0.721680f, 0.326172f, -1.0625f, -29.1875f, 30.0000f, 31, 32}, // 7db2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7db3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7db4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7db5 @@ -13345,7 +13646,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dbe - {0.286621f, 0.288574f, 0.301758f, 0.304199f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7dbf + {0.658691f, 0.311523f, 0.673828f, 0.327148f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 7dbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc2 @@ -13356,15 +13657,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dc9 - {0.157227f, 0.396484f, 0.172363f, 0.411621f, -0.3125f, -28.1250f, 30.0000f, 31, 31}, // 7dca + {0.429199f, 0.414551f, 0.444336f, 0.429688f, -0.3125f, -28.1250f, 30.0000f, 31, 31}, // 7dca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dcb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dcc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dcd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dce - {0.501465f, 0.018066f, 0.517578f, 0.033691f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7dcf + {0.757324f, 0.042480f, 0.773438f, 0.058105f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7dcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd0 - {0.567383f, 0.128906f, 0.583008f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dd1 - {0.583496f, 0.128906f, 0.599121f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dd2 + {0.532227f, 0.145508f, 0.547852f, 0.161133f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dd1 + {0.811523f, 0.145508f, 0.827148f, 0.161133f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7dd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd5 @@ -13372,13 +13673,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dd9 - {0.599609f, 0.128906f, 0.615234f, 0.144531f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7dda + {0.889160f, 0.146973f, 0.904785f, 0.162598f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7dda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ddb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ddc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ddd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ddf - {0.615723f, 0.128906f, 0.631348f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de0 + {0.385742f, 0.148438f, 0.401367f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de3 @@ -13386,19 +13687,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7de7 - {0.631836f, 0.128906f, 0.647461f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de8 - {0.647949f, 0.128906f, 0.663574f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de9 + {0.441406f, 0.148438f, 0.457031f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de8 + {0.457520f, 0.148438f, 0.473145f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7de9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7deb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ded {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dee - {0.716797f, 0.128906f, 0.732422f, 0.144531f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 7def + {0.473633f, 0.148438f, 0.489258f, 0.164063f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 7def {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df3 - {0.553711f, 0.019043f, 0.569824f, 0.034668f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7df4 + {0.773926f, 0.042480f, 0.790039f, 0.058105f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7df4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7df7 @@ -13411,10 +13712,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7dff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e00 - {0.393066f, 0.020996f, 0.409180f, 0.036621f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e01 + {0.631836f, 0.042969f, 0.647949f, 0.058594f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e03 - {0.455566f, 0.023926f, 0.471680f, 0.039551f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e04 + {0.648438f, 0.042969f, 0.664551f, 0.058594f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e07 @@ -13437,7 +13738,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e1a - {0.732910f, 0.128906f, 0.748535f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e1b + {0.489746f, 0.148438f, 0.505371f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e1e @@ -13448,15 +13749,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e25 - {0.749023f, 0.128906f, 0.764648f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e26 + {0.581055f, 0.148438f, 0.596680f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e2a - {0.765137f, 0.128906f, 0.780762f, 0.144531f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 7e2b + {0.923828f, 0.148438f, 0.939453f, 0.164063f, -1.0000f, -29.3125f, 30.0000f, 32, 32}, // 7e2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e2d - {0.781250f, 0.128906f, 0.796875f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e2e + {0.939941f, 0.148438f, 0.955566f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e31 @@ -13472,10 +13773,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e3d - {0.797363f, 0.128906f, 0.812988f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e3e + {0.956055f, 0.148438f, 0.971680f, 0.164063f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e40 - {0.450195f, 0.288574f, 0.465332f, 0.304199f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 7e41 + {0.333008f, 0.312012f, 0.348145f, 0.327637f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 7e41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e44 @@ -13484,7 +13785,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e49 - {0.472168f, 0.024414f, 0.488281f, 0.040039f, -1.1250f, -29.1875f, 30.0000f, 33, 32}, // 7e4a + {0.665039f, 0.043945f, 0.681152f, 0.059570f, -1.1250f, -29.1875f, 30.0000f, 33, 32}, // 7e4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e4d @@ -13494,8 +13795,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e53 - {0.813477f, 0.128906f, 0.829102f, 0.144531f, -1.1875f, -29.1875f, 30.0000f, 32, 32}, // 7e54 - {0.859375f, 0.128906f, 0.875000f, 0.144531f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7e55 + {0.972168f, 0.148438f, 0.987793f, 0.164063f, -1.1875f, -29.1875f, 30.0000f, 32, 32}, // 7e54 + {0.866699f, 0.148926f, 0.882324f, 0.164551f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 7e55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e58 @@ -13519,10 +13820,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e6c - {0.172852f, 0.396484f, 0.187988f, 0.411621f, -0.1250f, -29.0000f, 30.0000f, 31, 31}, // 7e6d + {0.444824f, 0.414551f, 0.459961f, 0.429688f, -0.1250f, -29.0000f, 30.0000f, 31, 31}, // 7e6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e6f - {0.359375f, 0.026367f, 0.375488f, 0.041992f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e70 + {0.681641f, 0.043945f, 0.697754f, 0.059570f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 7e70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e73 @@ -13534,7 +13835,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e7b - {0.875488f, 0.128906f, 0.891113f, 0.144531f, -1.3125f, -29.1875f, 30.0000f, 32, 32}, // 7e7c + {0.905273f, 0.149414f, 0.920898f, 0.165039f, -1.3125f, -29.1875f, 30.0000f, 32, 32}, // 7e7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e7f @@ -13550,7 +13851,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e8b - {0.891602f, 0.128906f, 0.907227f, 0.144531f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e8c + {0.096680f, 0.150391f, 0.112305f, 0.166016f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 7e8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7e8f @@ -13577,7 +13878,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ea4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ea5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ea6 - {0.496582f, 0.288574f, 0.511719f, 0.304199f, -0.1875f, -28.8750f, 30.0000f, 31, 32}, // 7ea7 + {0.789551f, 0.312012f, 0.804688f, 0.327637f, -0.1875f, -28.8750f, 30.0000f, 31, 32}, // 7ea7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ea8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ea9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eaa @@ -13595,13 +13896,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eb8 - {0.512207f, 0.288574f, 0.527344f, 0.304199f, 0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7eb9 + {0.773438f, 0.312500f, 0.788574f, 0.328125f, 0.0625f, -29.1875f, 30.0000f, 31, 32}, // 7eb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ebb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ebc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ebd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ebe - {0.555664f, 0.396484f, 0.570801f, 0.411621f, -0.6875f, -28.9375f, 30.0000f, 31, 31}, // 7ebf + {0.750000f, 0.414551f, 0.765137f, 0.429688f, -0.6875f, -28.9375f, 30.0000f, 31, 31}, // 7ebf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec2 @@ -13610,7 +13911,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec7 - {0.625488f, 0.288574f, 0.640625f, 0.304199f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 7ec8 + {0.192871f, 0.313477f, 0.208008f, 0.329102f, -0.1875f, -29.0625f, 30.0000f, 31, 32}, // 7ec8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ec9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ecb @@ -13633,7 +13934,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7edc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7edd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ede - {0.830566f, 0.288574f, 0.845703f, 0.304199f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 7edf + {0.208496f, 0.313477f, 0.223633f, 0.329102f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 7edf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee2 @@ -13641,13 +13942,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee6 - {0.451660f, 0.524902f, 0.466797f, 0.539551f, -0.4375f, -28.3125f, 30.0000f, 31, 30}, // 7ee7 + {0.419434f, 0.554199f, 0.434570f, 0.568848f, -0.4375f, -28.3125f, 30.0000f, 31, 30}, // 7ee7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ee9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eeb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eec - {0.846191f, 0.288574f, 0.861816f, 0.303711f, -1.1875f, -29.0000f, 30.0000f, 32, 31}, // 7eed + {0.497559f, 0.313477f, 0.513184f, 0.328613f, -1.1875f, -29.0000f, 30.0000f, 32, 31}, // 7eed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7eef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ef0 @@ -13685,10 +13986,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f12 - {0.078125f, 0.396973f, 0.093262f, 0.412109f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 7f13 + {0.460449f, 0.415039f, 0.475586f, 0.430176f, -0.0625f, -28.8750f, 30.0000f, 31, 31}, // 7f13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f15 - {0.912109f, 0.288574f, 0.927246f, 0.304199f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 7f16 + {0.513672f, 0.313477f, 0.528809f, 0.329102f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 7f16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f19 @@ -13707,7 +14008,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f28 - {0.927734f, 0.288574f, 0.942871f, 0.304199f, -0.8125f, -29.2500f, 30.0000f, 31, 32}, // 7f29 + {0.640625f, 0.313477f, 0.655762f, 0.329102f, -0.8125f, -29.2500f, 30.0000f, 31, 32}, // 7f29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f2c @@ -13720,7 +14021,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f33 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f35 - {0.943359f, 0.288574f, 0.958984f, 0.303711f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 7f36 + {0.690918f, 0.313477f, 0.706543f, 0.328613f, -0.6250f, -28.9375f, 30.0000f, 32, 31}, // 7f36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f39 @@ -13747,7 +14048,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f4f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f50 - {0.422363f, 0.678711f, 0.435547f, 0.693359f, 1.5000f, -27.3750f, 30.0000f, 27, 30}, // 7f51 + {0.111816f, 0.719238f, 0.125000f, 0.733887f, 1.5000f, -27.3750f, 30.0000f, 27, 30}, // 7f51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f53 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f54 @@ -13772,20 +14073,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f69 - {0.916992f, 0.524902f, 0.932129f, 0.539551f, -0.3125f, -27.8125f, 30.0000f, 31, 30}, // 7f6a + {0.435059f, 0.554199f, 0.450195f, 0.568848f, -0.3125f, -27.8125f, 30.0000f, 31, 30}, // 7f6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f6d - {0.688477f, 0.525391f, 0.703125f, 0.540527f, 1.0000f, -28.3750f, 30.0000f, 30, 31}, // 7f6e + {0.721680f, 0.554199f, 0.736328f, 0.569336f, 1.0000f, -28.3750f, 30.0000f, 30, 31}, // 7f6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f6f - {0.365723f, 0.616211f, 0.379883f, 0.631348f, 0.0625f, -28.3125f, 30.0000f, 29, 31}, // 7f70 + {0.150391f, 0.643066f, 0.164551f, 0.658203f, 0.0625f, -28.3125f, 30.0000f, 29, 31}, // 7f70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f71 - {0.868652f, 0.525391f, 0.883789f, 0.540039f, -0.3125f, -27.6875f, 30.0000f, 31, 30}, // 7f72 + {0.167969f, 0.554688f, 0.183105f, 0.569336f, -0.3125f, -27.6875f, 30.0000f, 31, 30}, // 7f72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f76 - {0.317383f, 0.396973f, 0.332520f, 0.412109f, 0.0000f, -28.2500f, 30.0000f, 31, 31}, // 7f77 + {0.285156f, 0.415527f, 0.300293f, 0.430664f, 0.0000f, -28.2500f, 30.0000f, 31, 31}, // 7f77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f7a @@ -13799,16 +14100,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f84 - {0.976074f, 0.288574f, 0.991699f, 0.303711f, -0.8750f, -28.2500f, 30.0000f, 32, 31}, // 7f85 + {0.560059f, 0.313965f, 0.575684f, 0.329102f, -0.8750f, -28.2500f, 30.0000f, 32, 31}, // 7f85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f89 - {0.240723f, 0.289063f, 0.255859f, 0.304688f, 0.1250f, -29.6250f, 30.0000f, 31, 32}, // 7f8a + {0.576172f, 0.313965f, 0.591309f, 0.329590f, 0.1250f, -29.6250f, 30.0000f, 31, 32}, // 7f8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f8d - {0.907715f, 0.128906f, 0.923340f, 0.144531f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7f8e + {0.112793f, 0.150391f, 0.128418f, 0.166016f, -0.6875f, -29.4375f, 30.0000f, 32, 32}, // 7f8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7f91 @@ -13830,12 +14131,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa3 - {0.923828f, 0.128906f, 0.939453f, 0.144531f, -1.0625f, -29.5625f, 30.0000f, 32, 32}, // 7fa4 + {0.128906f, 0.150879f, 0.144531f, 0.166504f, -1.0625f, -29.5625f, 30.0000f, 32, 32}, // 7fa4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fa8 - {0.256348f, 0.289063f, 0.271484f, 0.304688f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // 7fa9 + {0.674316f, 0.313965f, 0.689453f, 0.329590f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // 7fa9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7faa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fac @@ -13855,11 +14156,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fbc - {0.976563f, 0.646973f, 0.990723f, 0.661621f, 0.1875f, -27.5625f, 30.0000f, 29, 30}, // 7fbd + {0.161621f, 0.676270f, 0.175781f, 0.690918f, 0.1875f, -27.5625f, 30.0000f, 29, 30}, // 7fbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fc0 - {0.370605f, 0.289063f, 0.386230f, 0.304199f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 7fc1 + {0.047363f, 0.314941f, 0.062988f, 0.330078f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 7fc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fc4 @@ -13870,13 +14171,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fc9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fcb - {0.601563f, 0.616211f, 0.616699f, 0.630371f, -0.5625f, -27.9375f, 30.0000f, 31, 29}, // 7fcc + {0.134766f, 0.643555f, 0.149902f, 0.657715f, -0.5625f, -27.9375f, 30.0000f, 31, 29}, // 7fcc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fcd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fd0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fd1 - {0.192871f, 0.647461f, 0.207031f, 0.662109f, 0.1875f, -27.5000f, 30.0000f, 29, 30}, // 7fd2 + {0.377441f, 0.676270f, 0.391602f, 0.690918f, 0.1875f, -27.5000f, 30.0000f, 29, 30}, // 7fd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fd5 @@ -13917,17 +14218,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ff8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ff9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ffa - {0.199219f, 0.525879f, 0.213867f, 0.541016f, -0.2500f, -28.7500f, 30.0000f, 30, 31}, // 7ffb - {0.591309f, 0.396973f, 0.606445f, 0.412109f, -0.3750f, -28.2500f, 30.0000f, 31, 31}, // 7ffc + {0.498535f, 0.555176f, 0.513184f, 0.570313f, -0.2500f, -28.7500f, 30.0000f, 30, 31}, // 7ffb + {0.814453f, 0.415527f, 0.829590f, 0.430664f, -0.3750f, -28.2500f, 30.0000f, 31, 31}, // 7ffc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ffd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7ffe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 7fff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8000 - {0.639160f, 0.396973f, 0.654297f, 0.412109f, -0.8750f, -29.0000f, 30.0000f, 31, 31}, // 8001 + {0.300781f, 0.416016f, 0.315918f, 0.431152f, -0.8750f, -29.0000f, 30.0000f, 31, 31}, // 8001 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8002 - {0.686523f, 0.396973f, 0.701660f, 0.412109f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 8003 + {0.930664f, 0.416016f, 0.945801f, 0.431152f, -0.6250f, -29.1250f, 30.0000f, 31, 31}, // 8003 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8004 - {0.657715f, 0.289063f, 0.672852f, 0.304688f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 8005 + {0.080078f, 0.314941f, 0.095215f, 0.330566f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 8005 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8006 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8007 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8008 @@ -13938,14 +14239,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 800d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 800e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 800f - {0.939941f, 0.128906f, 0.955566f, 0.144531f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 8010 + {0.755859f, 0.150879f, 0.771484f, 0.166504f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 8010 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8011 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8012 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8013 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8014 - {0.956055f, 0.128906f, 0.971680f, 0.144531f, -1.1250f, -28.9375f, 30.0000f, 32, 32}, // 8015 + {0.401855f, 0.151367f, 0.417480f, 0.166992f, -1.1250f, -28.9375f, 30.0000f, 32, 32}, // 8015 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8016 - {0.718262f, 0.396973f, 0.733398f, 0.412109f, -1.0000f, -28.8750f, 30.0000f, 31, 31}, // 8017 + {0.946289f, 0.416016f, 0.961426f, 0.431152f, -1.0000f, -28.8750f, 30.0000f, 31, 31}, // 8017 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8018 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8019 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 801a @@ -13973,7 +14274,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8030 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8031 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8032 - {0.277832f, 0.526855f, 0.292969f, 0.541504f, -0.3750f, -27.4375f, 30.0000f, 31, 30}, // 8033 + {0.821289f, 0.555176f, 0.836426f, 0.569824f, -0.3750f, -27.4375f, 30.0000f, 31, 30}, // 8033 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8034 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8035 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8036 @@ -14008,7 +14309,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8053 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8054 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8055 - {0.338379f, 0.529785f, 0.353516f, 0.544434f, -0.0625f, -28.1875f, 30.0000f, 31, 30}, // 8056 + {0.924805f, 0.555176f, 0.939941f, 0.569824f, -0.0625f, -28.1875f, 30.0000f, 31, 30}, // 8056 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8057 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8058 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8059 @@ -14016,7 +14317,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 805b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 805c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 805d - {0.437500f, 0.664063f, 0.451172f, 0.678711f, 1.5625f, -27.6250f, 30.0000f, 28, 30}, // 805e + {0.739258f, 0.701172f, 0.752930f, 0.715820f, 1.5625f, -27.6250f, 30.0000f, 28, 30}, // 805e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 805f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8060 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8061 @@ -14036,12 +14337,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 806f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8070 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8071 - {0.733887f, 0.396973f, 0.749023f, 0.412109f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 8072 + {0.961914f, 0.416016f, 0.977051f, 0.431152f, -0.1875f, -29.0000f, 30.0000f, 31, 31}, // 8072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8073 - {0.972168f, 0.128906f, 0.987793f, 0.144531f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 8074 + {0.417969f, 0.151367f, 0.433594f, 0.166992f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 8074 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8075 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8076 - {0.524414f, 0.129395f, 0.540039f, 0.145020f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 8077 + {0.663086f, 0.151367f, 0.678711f, 0.166992f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 8077 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8078 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8079 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 807a @@ -14059,10 +14360,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8086 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8087 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8088 - {0.331055f, 0.653320f, 0.344238f, 0.668945f, 1.5625f, -29.3125f, 30.0000f, 27, 32}, // 8089 + {0.329102f, 0.687500f, 0.342285f, 0.703125f, 1.5625f, -29.3125f, 30.0000f, 27, 32}, // 8089 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 808a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 808b - {0.124512f, 0.445801f, 0.140137f, 0.460449f, -1.1250f, -27.1875f, 30.0000f, 32, 30}, // 808c + {0.203125f, 0.470703f, 0.218750f, 0.485352f, -1.1250f, -27.1875f, 30.0000f, 32, 30}, // 808c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 808d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 808e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 808f @@ -14072,35 +14373,35 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8093 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8094 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8095 - {0.900391f, 0.681641f, 0.913086f, 0.696777f, 1.9375f, -29.0625f, 30.0000f, 26, 31}, // 8096 + {0.014160f, 0.720703f, 0.026855f, 0.735840f, 1.9375f, -29.0625f, 30.0000f, 26, 31}, // 8096 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8097 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8098 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8099 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 809a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 809b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 809c - {0.354004f, 0.529785f, 0.369141f, 0.544434f, -0.1875f, -27.5625f, 30.0000f, 31, 30}, // 809d + {0.909668f, 0.555664f, 0.924805f, 0.570313f, -0.1875f, -27.5625f, 30.0000f, 31, 30}, // 809d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 809e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 809f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a1 - {0.664063f, 0.129395f, 0.679688f, 0.145020f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 80a2 + {0.354492f, 0.152832f, 0.370117f, 0.168457f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 80a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a4 - {0.000000f, 0.531250f, 0.015137f, 0.545898f, -0.5000f, -27.3750f, 30.0000f, 31, 30}, // 80a5 + {0.955566f, 0.555664f, 0.970703f, 0.570313f, -0.5000f, -27.3750f, 30.0000f, 31, 30}, // 80a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80a8 - {0.107910f, 0.530762f, 0.122559f, 0.545898f, -0.4375f, -28.3125f, 30.0000f, 30, 31}, // 80a9 - {0.191895f, 0.290039f, 0.207520f, 0.305176f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 80aa + {0.786621f, 0.556152f, 0.801270f, 0.571289f, -0.4375f, -28.3125f, 30.0000f, 30, 31}, // 80a9 + {0.591797f, 0.314941f, 0.607422f, 0.330078f, -1.0000f, -28.8125f, 30.0000f, 32, 31}, // 80aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ae - {0.093750f, 0.397461f, 0.108887f, 0.412598f, -0.2500f, -29.0000f, 30.0000f, 31, 31}, // 80af + {0.977539f, 0.416016f, 0.992676f, 0.431152f, -0.2500f, -29.0000f, 30.0000f, 31, 31}, // 80af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b1 - {0.649414f, 0.616211f, 0.663574f, 0.631348f, 0.7500f, -29.2500f, 30.0000f, 29, 31}, // 80b2 + {0.532715f, 0.643066f, 0.546875f, 0.658203f, 0.7500f, -29.2500f, 30.0000f, 29, 31}, // 80b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b5 @@ -14108,7 +14409,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80b9 - {0.829590f, 0.129395f, 0.845215f, 0.145020f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 80ba + {0.697754f, 0.152832f, 0.713379f, 0.168457f, -1.0625f, -29.1875f, 30.0000f, 32, 32}, // 80ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80bd @@ -14117,18 +14418,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c2 - {0.796875f, 0.746582f, 0.809082f, 0.760742f, 3.0625f, -27.5625f, 30.0000f, 25, 29}, // 80c3 + {0.091797f, 0.805176f, 0.104004f, 0.819336f, 3.0625f, -27.5625f, 30.0000f, 25, 29}, // 80c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c5 - {0.233887f, 0.445801f, 0.249512f, 0.460449f, -0.8750f, -27.6250f, 30.0000f, 32, 30}, // 80c6 + {0.078613f, 0.471191f, 0.094238f, 0.485840f, -0.8750f, -27.6250f, 30.0000f, 32, 30}, // 80c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80cb - {0.538574f, 0.397461f, 0.553711f, 0.412598f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 80cc + {0.848145f, 0.416504f, 0.863281f, 0.431641f, -0.2500f, -28.8125f, 30.0000f, 31, 31}, // 80cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80cd - {0.418945f, 0.290039f, 0.434082f, 0.305664f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 80ce + {0.607910f, 0.314941f, 0.623047f, 0.330566f, -0.5625f, -29.1250f, 30.0000f, 31, 32}, // 80ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80d1 @@ -14144,7 +14445,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80dd - {0.540527f, 0.129883f, 0.556152f, 0.145508f, -0.9375f, -29.4375f, 30.0000f, 32, 32}, // 80de + {0.827637f, 0.152832f, 0.843262f, 0.168457f, -0.9375f, -29.4375f, 30.0000f, 32, 32}, // 80de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80e1 @@ -14166,27 +14467,27 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f3 - {0.015625f, 0.533203f, 0.030762f, 0.547852f, -1.1875f, -27.6250f, 30.0000f, 31, 30}, // 80f4 + {0.260742f, 0.556641f, 0.275879f, 0.571289f, -1.1875f, -27.6250f, 30.0000f, 31, 30}, // 80f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f7 - {0.670898f, 0.397461f, 0.686035f, 0.412598f, -1.0625f, -29.2500f, 30.0000f, 31, 31}, // 80f8 + {0.331543f, 0.416992f, 0.346680f, 0.432129f, -1.0625f, -29.2500f, 30.0000f, 31, 31}, // 80f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80fc - {0.465820f, 0.290039f, 0.480957f, 0.305664f, -0.1875f, -29.3750f, 30.0000f, 31, 32}, // 80fd + {0.063477f, 0.315430f, 0.078613f, 0.331055f, -0.1875f, -29.3750f, 30.0000f, 31, 32}, // 80fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 80ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8100 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8101 - {0.224609f, 0.290527f, 0.240234f, 0.305664f, -0.5625f, -28.4375f, 30.0000f, 32, 31}, // 8102 + {0.143555f, 0.315430f, 0.159180f, 0.330566f, -0.5625f, -28.4375f, 30.0000f, 32, 31}, // 8102 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8103 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8104 - {0.797363f, 0.397461f, 0.812500f, 0.412598f, 0.1875f, -29.2500f, 30.0000f, 31, 31}, // 8105 + {0.396973f, 0.416992f, 0.412109f, 0.432129f, 0.1875f, -29.2500f, 30.0000f, 31, 31}, // 8105 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8106 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8107 - {0.208008f, 0.291016f, 0.223633f, 0.306152f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 8108 + {0.159668f, 0.315430f, 0.175293f, 0.330566f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 8108 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8109 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 810a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 810b @@ -14195,7 +14496,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 810e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 810f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8110 - {0.273926f, 0.130371f, 0.289551f, 0.145996f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 8111 + {0.843750f, 0.153320f, 0.859375f, 0.168945f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 8111 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8112 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8113 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8114 @@ -14204,7 +14505,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8117 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8118 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8119 - {0.861328f, 0.397461f, 0.876465f, 0.412598f, -1.0000f, -28.3125f, 30.0000f, 31, 31}, // 811a + {0.412598f, 0.416992f, 0.427734f, 0.432129f, -1.0000f, -28.3125f, 30.0000f, 31, 31}, // 811a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 811b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 811c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 811d @@ -14227,15 +14528,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 812e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 812f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8130 - {0.481445f, 0.290039f, 0.496582f, 0.305664f, -0.2500f, -29.0625f, 30.0000f, 31, 32}, // 8131 + {0.111328f, 0.315918f, 0.126465f, 0.331543f, -0.2500f, -29.0625f, 30.0000f, 31, 32}, // 8131 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8132 - {0.701660f, 0.177246f, 0.717773f, 0.192383f, -1.2500f, -28.5625f, 30.0000f, 33, 31}, // 8133 + {0.924805f, 0.196777f, 0.940918f, 0.211914f, -1.2500f, -28.5625f, 30.0000f, 33, 31}, // 8133 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8134 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8135 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8136 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8137 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8138 - {0.505371f, 0.445801f, 0.520996f, 0.460449f, -0.7500f, -27.9375f, 30.0000f, 32, 30}, // 8139 + {0.187012f, 0.471191f, 0.202637f, 0.485840f, -0.7500f, -27.9375f, 30.0000f, 32, 30}, // 8139 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 813a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 813b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 813c @@ -14258,12 +14559,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 814d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 814e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 814f - {0.290039f, 0.130371f, 0.305664f, 0.145996f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 8150 + {0.209473f, 0.154785f, 0.225098f, 0.170410f, -0.6875f, -29.1875f, 30.0000f, 32, 32}, // 8150 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8151 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8152 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8153 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8154 - {0.718262f, 0.177246f, 0.734375f, 0.192383f, -1.2500f, -29.0625f, 30.0000f, 33, 31}, // 8155 + {0.941406f, 0.196777f, 0.957520f, 0.211914f, -1.2500f, -29.0625f, 30.0000f, 33, 31}, // 8155 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8156 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8157 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8158 @@ -14290,7 +14591,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 816d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 816e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 816f - {0.647461f, 0.445801f, 0.663086f, 0.460449f, -1.3125f, -27.8125f, 30.0000f, 32, 30}, // 8170 + {0.615723f, 0.471191f, 0.631348f, 0.485840f, -1.3125f, -27.8125f, 30.0000f, 32, 30}, // 8170 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8171 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8172 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8173 @@ -14298,8 +14599,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8175 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8176 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8177 - {0.779785f, 0.445801f, 0.795410f, 0.460449f, -0.7500f, -28.0000f, 30.0000f, 32, 30}, // 8178 - {0.375977f, 0.026367f, 0.392090f, 0.041992f, -1.3750f, -29.1250f, 30.0000f, 33, 32}, // 8179 + {0.666504f, 0.471191f, 0.682129f, 0.485840f, -0.7500f, -28.0000f, 30.0000f, 32, 30}, // 8178 + {0.176758f, 0.044922f, 0.192871f, 0.060547f, -1.3750f, -29.1250f, 30.0000f, 33, 32}, // 8179 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 817a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 817b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 817c @@ -14332,9 +14633,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8197 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8198 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8199 - {0.334473f, 0.292480f, 0.349609f, 0.308105f, -0.6875f, -29.5000f, 30.0000f, 31, 32}, // 819a + {0.175781f, 0.315918f, 0.190918f, 0.331543f, -0.6875f, -29.5000f, 30.0000f, 31, 32}, // 819a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 819b - {0.734863f, 0.177246f, 0.750977f, 0.192383f, -1.4375f, -28.6875f, 30.0000f, 33, 31}, // 819c + {0.958008f, 0.196777f, 0.974121f, 0.211914f, -1.4375f, -28.6875f, 30.0000f, 33, 31}, // 819c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 819d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 819e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 819f @@ -14346,7 +14647,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81a7 - {0.060547f, 0.028809f, 0.076660f, 0.044434f, -1.5000f, -29.1250f, 30.0000f, 33, 32}, // 81a8 + {0.209473f, 0.044922f, 0.225586f, 0.060547f, -1.5000f, -29.1250f, 30.0000f, 33, 32}, // 81a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81ab @@ -14389,7 +14690,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d2 - {0.751465f, 0.177246f, 0.767578f, 0.192383f, -1.0625f, -29.1250f, 30.0000f, 33, 31}, // 81d3 + {0.974609f, 0.196777f, 0.990723f, 0.211914f, -1.0625f, -29.1250f, 30.0000f, 33, 31}, // 81d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81d6 @@ -14405,24 +14706,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e2 - {0.408203f, 0.664551f, 0.421875f, 0.679199f, 2.5000f, -27.3750f, 30.0000f, 28, 30}, // 81e3 + {0.282227f, 0.701660f, 0.295898f, 0.716309f, 2.5000f, -27.3750f, 30.0000f, 28, 30}, // 81e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e7 - {0.878418f, 0.555664f, 0.892578f, 0.571289f, 1.5625f, -29.2500f, 30.0000f, 29, 32}, // 81e8 + {0.000000f, 0.585449f, 0.014160f, 0.601074f, 1.5625f, -29.2500f, 30.0000f, 29, 32}, // 81e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81e9 - {0.463867f, 0.130859f, 0.475098f, 0.146484f, 4.0000f, -29.6250f, 30.0000f, 23, 32}, // 81ea + {0.974121f, 0.759766f, 0.985352f, 0.775391f, 4.0000f, -29.6250f, 30.0000f, 23, 32}, // 81ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81ec - {0.306152f, 0.130371f, 0.321777f, 0.145996f, -0.3750f, -29.3750f, 30.0000f, 32, 32}, // 81ed + {0.225586f, 0.154785f, 0.241211f, 0.170410f, -0.3750f, -29.3750f, 30.0000f, 32, 32}, // 81ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f2 - {0.422363f, 0.664551f, 0.437012f, 0.678223f, 0.3750f, -27.1250f, 30.0000f, 30, 28}, // 81f3 - {0.475586f, 0.130371f, 0.491211f, 0.145996f, -0.2500f, -29.0000f, 30.0000f, 32, 32}, // 81f4 + {0.088867f, 0.703125f, 0.103516f, 0.716797f, 0.3750f, -27.1250f, 30.0000f, 30, 28}, // 81f3 + {0.241699f, 0.154785f, 0.257324f, 0.170410f, -0.2500f, -29.0000f, 30.0000f, 32, 32}, // 81f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 81f7 @@ -14442,13 +14743,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8205 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8206 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8207 - {0.125000f, 0.397949f, 0.140137f, 0.413086f, 0.0000f, -28.8125f, 30.0000f, 31, 31}, // 8208 + {0.511230f, 0.416992f, 0.526367f, 0.432129f, 0.0000f, -28.8125f, 30.0000f, 31, 31}, // 8208 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8209 - {0.386719f, 0.295410f, 0.401855f, 0.311035f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 820a + {0.126953f, 0.316406f, 0.142090f, 0.332031f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 820a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 820b - {0.837402f, 0.616211f, 0.851563f, 0.631348f, 0.2500f, -28.9375f, 30.0000f, 29, 31}, // 820c + {0.015625f, 0.643555f, 0.029785f, 0.658691f, 0.2500f, -28.9375f, 30.0000f, 29, 31}, // 820c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 820d - {0.491699f, 0.130371f, 0.507324f, 0.145996f, -0.6875f, -29.7500f, 30.0000f, 32, 32}, // 820e + {0.548340f, 0.154785f, 0.563965f, 0.170410f, -0.6875f, -29.7500f, 30.0000f, 32, 32}, // 820e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 820f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8210 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8211 @@ -14457,15 +14758,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8214 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8215 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8216 - {0.447754f, 0.130859f, 0.463379f, 0.146484f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 8217 + {0.564453f, 0.154785f, 0.580078f, 0.170410f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 8217 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8218 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8219 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 821a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 821b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 821c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 821d - {0.698730f, 0.130859f, 0.714355f, 0.146484f, -0.6250f, -29.6250f, 30.0000f, 32, 32}, // 821e - {0.402344f, 0.295898f, 0.417480f, 0.311523f, 0.0625f, -29.1875f, 30.0000f, 31, 32}, // 821f + {0.679199f, 0.155273f, 0.694824f, 0.170898f, -0.6250f, -29.6250f, 30.0000f, 32, 32}, // 821e + {0.016113f, 0.316895f, 0.031250f, 0.332520f, 0.0625f, -29.1875f, 30.0000f, 31, 32}, // 821f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8220 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8221 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8222 @@ -14476,9 +14777,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8227 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8228 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8229 - {0.507813f, 0.131836f, 0.523438f, 0.147461f, -0.8750f, -29.5000f, 30.0000f, 32, 32}, // 822a + {0.713867f, 0.155273f, 0.729492f, 0.170898f, -0.8750f, -29.5000f, 30.0000f, 32, 32}, // 822a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 822b - {0.209473f, 0.132324f, 0.225098f, 0.147949f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 822c + {0.729980f, 0.155273f, 0.745605f, 0.170898f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 822c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 822d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 822e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 822f @@ -14488,10 +14789,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8233 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8234 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8235 - {0.905273f, 0.446289f, 0.919922f, 0.461914f, -0.8125f, -29.5625f, 30.0000f, 30, 32}, // 8236 + {0.757324f, 0.471191f, 0.771973f, 0.486816f, -0.8125f, -29.5625f, 30.0000f, 30, 32}, // 8236 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8237 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8238 - {0.225586f, 0.132324f, 0.241211f, 0.147949f, -0.8125f, -29.5000f, 30.0000f, 32, 32}, // 8239 + {0.597168f, 0.155762f, 0.612793f, 0.171387f, -0.8125f, -29.5000f, 30.0000f, 32, 32}, // 8239 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 823a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 823b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 823c @@ -14505,7 +14806,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8244 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8245 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8246 - {0.241699f, 0.132324f, 0.257324f, 0.147949f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 8247 + {0.613281f, 0.155762f, 0.628906f, 0.171387f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 8247 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8248 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8249 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 824a @@ -14536,7 +14837,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8263 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8264 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8265 - {0.257813f, 0.132324f, 0.273438f, 0.147949f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 8266 + {0.048340f, 0.156250f, 0.063965f, 0.171875f, -1.0000f, -29.5000f, 30.0000f, 32, 32}, // 8266 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8267 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8268 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8269 @@ -14545,10 +14846,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 826c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 826d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 826e - {0.493652f, 0.397949f, 0.508789f, 0.413086f, 0.5000f, -28.6250f, 30.0000f, 31, 31}, // 826f + {0.878906f, 0.416992f, 0.894043f, 0.432129f, 0.5000f, -28.6250f, 30.0000f, 31, 31}, // 826f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8270 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8271 - {0.250000f, 0.446777f, 0.265625f, 0.461426f, -0.6250f, -29.1875f, 30.0000f, 32, 30}, // 8272 + {0.470215f, 0.471680f, 0.485840f, 0.486328f, -0.6250f, -29.1875f, 30.0000f, 32, 30}, // 8272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8273 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8274 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8275 @@ -14573,7 +14874,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8288 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8289 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 828a - {0.509277f, 0.397949f, 0.524414f, 0.413086f, -0.0625f, -28.9375f, 30.0000f, 31, 31}, // 828b + {0.911621f, 0.416992f, 0.926758f, 0.432129f, -0.0625f, -28.9375f, 30.0000f, 31, 31}, // 828b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 828c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 828d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 828e @@ -14591,7 +14892,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 829a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 829b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 829c - {0.111816f, 0.296387f, 0.127441f, 0.311523f, -0.3750f, -28.7500f, 30.0000f, 32, 31}, // 829d + {0.000000f, 0.317383f, 0.015625f, 0.332520f, -0.3750f, -28.7500f, 30.0000f, 32, 31}, // 829d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 829e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 829f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82a0 @@ -14611,19 +14912,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b0 - {0.606934f, 0.397949f, 0.622070f, 0.413086f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 82b1 + {0.378906f, 0.417480f, 0.394043f, 0.432617f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 82b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b2 - {0.302246f, 0.296875f, 0.317383f, 0.312500f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 82b3 + {0.738770f, 0.317383f, 0.753906f, 0.333008f, -0.5000f, -29.1875f, 30.0000f, 31, 32}, // 82b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b7 - {0.925781f, 0.397949f, 0.940918f, 0.413086f, 0.0000f, -28.7500f, 30.0000f, 31, 31}, // 82b8 + {0.863770f, 0.418457f, 0.878906f, 0.433594f, 0.0000f, -28.7500f, 30.0000f, 31, 31}, // 82b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82bc - {0.958496f, 0.397949f, 0.973633f, 0.413086f, -0.3125f, -29.1875f, 30.0000f, 31, 31}, // 82bd + {0.830078f, 0.418945f, 0.845215f, 0.434082f, -0.3125f, -29.1875f, 30.0000f, 31, 31}, // 82bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82c0 @@ -14649,7 +14950,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82d6 - {0.974121f, 0.397949f, 0.989258f, 0.413086f, 0.0625f, -28.9375f, 30.0000f, 31, 31}, // 82d7 + {0.093750f, 0.419434f, 0.108887f, 0.434570f, 0.0625f, -28.9375f, 30.0000f, 31, 31}, // 82d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82da @@ -14663,8 +14964,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e4 - {0.261230f, 0.533691f, 0.275879f, 0.548828f, 0.1250f, -28.8750f, 30.0000f, 30, 31}, // 82e5 - {0.915527f, 0.555664f, 0.929688f, 0.571289f, 0.3750f, -29.0000f, 30.0000f, 29, 32}, // 82e6 + {0.450684f, 0.556641f, 0.465332f, 0.571777f, 0.1250f, -28.8750f, 30.0000f, 30, 31}, // 82e5 + {0.167969f, 0.585449f, 0.182129f, 0.601074f, 0.3750f, -29.0000f, 30.0000f, 29, 32}, // 82e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82e9 @@ -14675,7 +14976,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82f0 - {0.140625f, 0.398438f, 0.155762f, 0.413574f, -0.5000f, -28.6875f, 30.0000f, 31, 31}, // 82f1 + {0.894531f, 0.419434f, 0.909668f, 0.434570f, -0.5000f, -28.6875f, 30.0000f, 31, 31}, // 82f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82f4 @@ -14692,7 +14993,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 82ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8300 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8301 - {0.413574f, 0.398438f, 0.428711f, 0.413574f, -0.1875f, -28.8750f, 30.0000f, 31, 31}, // 8302 + {0.347168f, 0.419922f, 0.362305f, 0.435059f, -0.1875f, -28.8750f, 30.0000f, 31, 31}, // 8302 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8303 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8304 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8305 @@ -14704,7 +15005,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 830b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 830c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 830d - {0.329590f, 0.446777f, 0.345215f, 0.461426f, -0.6250f, -28.9375f, 30.0000f, 32, 30}, // 830e + {0.522461f, 0.471680f, 0.538086f, 0.486328f, -0.6250f, -28.9375f, 30.0000f, 32, 30}, // 830e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 830f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8310 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8311 @@ -14740,11 +15041,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 832f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8330 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8331 - {0.046387f, 0.534180f, 0.061035f, 0.549316f, 0.5000f, -29.1250f, 30.0000f, 30, 31}, // 8332 + {0.940430f, 0.556641f, 0.955078f, 0.571777f, 0.5000f, -29.1250f, 30.0000f, 30, 31}, // 8332 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8333 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8334 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8335 - {0.000000f, 0.297363f, 0.015625f, 0.312500f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 8336 + {0.224121f, 0.318359f, 0.239746f, 0.333496f, -0.8125f, -28.9375f, 30.0000f, 32, 31}, // 8336 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8337 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8338 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8339 @@ -14763,7 +15064,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8346 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8347 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8348 - {0.016113f, 0.298340f, 0.031250f, 0.313965f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 8349 + {0.240234f, 0.318359f, 0.255371f, 0.333984f, -0.2500f, -29.0000f, 30.0000f, 31, 32}, // 8349 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 834a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 834b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 834c @@ -14772,13 +15073,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 834f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8350 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8351 - {0.063965f, 0.299316f, 0.079590f, 0.314453f, -0.8125f, -29.1250f, 30.0000f, 32, 31}, // 8352 + {0.272461f, 0.318359f, 0.288086f, 0.333496f, -0.8125f, -29.1250f, 30.0000f, 32, 31}, // 8352 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8353 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8354 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8355 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8356 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8357 - {0.571289f, 0.398438f, 0.586426f, 0.413574f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 8358 + {0.616211f, 0.420410f, 0.631348f, 0.435547f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 8358 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8359 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 835a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 835b @@ -14809,7 +15110,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8374 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8375 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8376 - {0.354492f, 0.133789f, 0.370117f, 0.149414f, -0.7500f, -29.0625f, 30.0000f, 32, 32}, // 8377 + {0.064453f, 0.156250f, 0.080078f, 0.171875f, -0.7500f, -29.0625f, 30.0000f, 32, 32}, // 8377 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8378 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8379 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 837a @@ -14873,7 +15174,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83b6 - {0.080078f, 0.299316f, 0.095703f, 0.314453f, -1.0625f, -28.9375f, 30.0000f, 32, 31}, // 83b7 + {0.288574f, 0.318359f, 0.304199f, 0.333496f, -1.0625f, -28.9375f, 30.0000f, 32, 31}, // 83b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83ba @@ -14892,16 +15193,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83c9 - {0.749512f, 0.398438f, 0.764648f, 0.413574f, -0.8125f, -29.1250f, 30.0000f, 31, 31}, // 83ca + {0.362793f, 0.420898f, 0.377930f, 0.436035f, -0.8125f, -29.1250f, 30.0000f, 31, 31}, // 83ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83cb - {0.765137f, 0.398438f, 0.780273f, 0.413574f, 0.0625f, -29.1875f, 30.0000f, 31, 31}, // 83cc + {0.699707f, 0.420898f, 0.714844f, 0.436035f, 0.0625f, -29.1875f, 30.0000f, 31, 31}, // 83cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d2 - {0.031738f, 0.299805f, 0.047363f, 0.314941f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 83d3 + {0.722168f, 0.318359f, 0.737793f, 0.333496f, -0.6875f, -28.6875f, 30.0000f, 32, 31}, // 83d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d6 @@ -14910,7 +15211,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83db - {0.415039f, 0.136719f, 0.430664f, 0.152344f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 83dc + {0.080566f, 0.156250f, 0.096191f, 0.171875f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 83dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83df @@ -14929,7 +15230,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83ee - {0.047852f, 0.299805f, 0.062988f, 0.315430f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 83ef + {0.255859f, 0.319336f, 0.270996f, 0.334961f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 83ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 83f2 @@ -15007,7 +15308,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 843a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 843b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 843c - {0.431152f, 0.137207f, 0.446777f, 0.152832f, -0.3750f, -29.0625f, 30.0000f, 32, 32}, // 843d + {0.629395f, 0.156738f, 0.645020f, 0.172363f, -0.3750f, -29.0625f, 30.0000f, 32, 32}, // 843d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 843e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 843f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8440 @@ -15019,7 +15320,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8446 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8447 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8448 - {0.128906f, 0.138672f, 0.144531f, 0.154297f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 8449 + {0.645508f, 0.156738f, 0.661133f, 0.172363f, -0.6250f, -29.1875f, 30.0000f, 32, 32}, // 8449 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 844a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 844b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 844c @@ -15033,7 +15334,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8454 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8455 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8456 - {0.910645f, 0.398438f, 0.925781f, 0.413574f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 8457 + {0.316406f, 0.421875f, 0.331543f, 0.437012f, -0.7500f, -28.8125f, 30.0000f, 31, 31}, // 8457 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8458 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8459 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 845a @@ -15054,7 +15355,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8469 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 846a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 846b - {0.317871f, 0.300781f, 0.333008f, 0.316406f, -0.6875f, -29.1875f, 30.0000f, 31, 32}, // 846c + {0.445801f, 0.319824f, 0.460938f, 0.335449f, -0.6875f, -29.1875f, 30.0000f, 31, 32}, // 846c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 846d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 846e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 846f @@ -15130,7 +15431,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84b7 - {0.159180f, 0.302246f, 0.174805f, 0.317383f, -0.6250f, -28.7500f, 30.0000f, 32, 31}, // 84b8 + {0.031738f, 0.320313f, 0.047363f, 0.335449f, -0.6250f, -28.7500f, 30.0000f, 32, 31}, // 84b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84bb @@ -15142,14 +15443,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c3 - {0.350098f, 0.302246f, 0.365234f, 0.317871f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 84c4 + {0.461426f, 0.320313f, 0.476563f, 0.335938f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 84c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84ca - {0.816895f, 0.534180f, 0.832031f, 0.548828f, -0.2500f, -29.0625f, 30.0000f, 31, 30}, // 84cb + {0.384766f, 0.557617f, 0.399902f, 0.572266f, -0.2500f, -29.0625f, 30.0000f, 31, 30}, // 84cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 84ce @@ -15255,7 +15556,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8532 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8533 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8534 - {0.145020f, 0.138672f, 0.160645f, 0.154297f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 8535 + {0.145020f, 0.157715f, 0.160645f, 0.173340f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 8535 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8536 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8537 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8538 @@ -15334,7 +15635,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8581 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8582 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8583 - {0.096191f, 0.302734f, 0.111328f, 0.318359f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 8584 + {0.477051f, 0.320313f, 0.492188f, 0.335938f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 8584 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8585 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8586 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8587 @@ -15368,13 +15669,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a5 - {0.322266f, 0.139160f, 0.337891f, 0.154785f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 85a6 + {0.177246f, 0.157715f, 0.192871f, 0.173340f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 85a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85a9 - {0.338379f, 0.139160f, 0.354004f, 0.154785f, -0.5000f, -29.5000f, 30.0000f, 32, 32}, // 85aa - {0.000000f, 0.140137f, 0.015625f, 0.155762f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 85ab - {0.016113f, 0.140137f, 0.031738f, 0.155762f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 85ac + {0.193359f, 0.157715f, 0.208984f, 0.173340f, -0.5000f, -29.5000f, 30.0000f, 32, 32}, // 85aa + {0.161133f, 0.158203f, 0.176758f, 0.173828f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 85ab + {0.000000f, 0.159180f, 0.015625f, 0.174805f, -0.6250f, -29.2500f, 30.0000f, 32, 32}, // 85ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85af @@ -15435,7 +15736,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85e8 - {0.032227f, 0.140137f, 0.047852f, 0.155762f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 85e9 + {0.016113f, 0.159180f, 0.031738f, 0.174805f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 85e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85ec @@ -15453,7 +15754,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85fa - {0.048340f, 0.141602f, 0.063965f, 0.157227f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 85fb + {0.032227f, 0.159180f, 0.047852f, 0.174805f, -0.5625f, -29.1875f, 30.0000f, 32, 32}, // 85fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 85fe @@ -15538,22 +15839,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 864d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 864e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 864f - {0.266113f, 0.446777f, 0.280762f, 0.462402f, -0.8750f, -29.2500f, 30.0000f, 30, 32}, // 8650 + {0.538574f, 0.471680f, 0.553223f, 0.487305f, -0.8750f, -29.2500f, 30.0000f, 30, 32}, // 8650 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8651 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8652 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8653 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8654 - {0.064453f, 0.141602f, 0.080078f, 0.157227f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 8655 + {0.771973f, 0.159668f, 0.787598f, 0.175293f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 8655 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8656 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8657 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8658 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8659 - {0.941406f, 0.398438f, 0.956543f, 0.413574f, -1.1875f, -28.9375f, 30.0000f, 31, 31}, // 865a - {0.236816f, 0.398926f, 0.251953f, 0.414063f, -0.9375f, -28.9375f, 30.0000f, 31, 31}, // 865b - {0.127930f, 0.302734f, 0.143066f, 0.318359f, -0.6875f, -29.2500f, 30.0000f, 31, 32}, // 865c + {0.648438f, 0.421875f, 0.663574f, 0.437012f, -1.1875f, -28.9375f, 30.0000f, 31, 31}, // 865a + {0.782227f, 0.422852f, 0.797363f, 0.437988f, -0.9375f, -28.9375f, 30.0000f, 31, 31}, // 865b + {0.754395f, 0.320313f, 0.769531f, 0.335938f, -0.6875f, -29.2500f, 30.0000f, 31, 32}, // 865c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 865d - {0.080566f, 0.141602f, 0.096191f, 0.157227f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 865e - {0.268066f, 0.398926f, 0.283203f, 0.414063f, -0.4375f, -28.8750f, 30.0000f, 31, 31}, // 865f + {0.788086f, 0.159668f, 0.803711f, 0.175293f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 865e + {0.797852f, 0.422852f, 0.812988f, 0.437988f, -0.4375f, -28.8750f, 30.0000f, 31, 31}, // 865f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8660 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8661 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8662 @@ -15565,7 +15866,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8668 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8669 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 866a - {0.096680f, 0.141602f, 0.112305f, 0.157227f, -0.6250f, -29.5625f, 30.0000f, 32, 32}, // 866b + {0.273926f, 0.160156f, 0.289551f, 0.175781f, -0.6250f, -29.5625f, 30.0000f, 32, 32}, // 866b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 866c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 866d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 866e @@ -15596,7 +15897,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8687 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8688 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8689 - {0.175293f, 0.302734f, 0.190918f, 0.317871f, -0.8750f, -28.6875f, 30.0000f, 32, 31}, // 868a + {0.304688f, 0.321289f, 0.320313f, 0.336426f, -0.8750f, -28.6875f, 30.0000f, 32, 31}, // 868a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 868b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 868c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 868d @@ -15607,7 +15908,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8692 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8693 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8694 - {0.603027f, 0.446777f, 0.618652f, 0.461426f, -0.5000f, -27.8125f, 30.0000f, 32, 30}, // 8695 + {0.568359f, 0.471680f, 0.583984f, 0.486328f, -0.5000f, -27.8125f, 30.0000f, 32, 30}, // 8695 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8696 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8697 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8698 @@ -15657,13 +15958,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86c6 - {0.559570f, 0.302734f, 0.575195f, 0.317871f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 86c7 + {0.821289f, 0.321289f, 0.836914f, 0.336426f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 86c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86cc - {0.966797f, 0.616211f, 0.980957f, 0.631348f, 0.5000f, -28.7500f, 30.0000f, 29, 31}, // 86cd + {0.726563f, 0.644043f, 0.740723f, 0.659180f, 0.5000f, -28.7500f, 30.0000f, 29, 31}, // 86cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86d0 @@ -15696,7 +15997,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86ed - {0.112793f, 0.143555f, 0.128418f, 0.159180f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 86ee + {0.290039f, 0.160156f, 0.305664f, 0.175781f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 86ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 86f1 @@ -15855,7 +16156,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 878a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 878b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 878c - {0.641113f, 0.302734f, 0.656738f, 0.317871f, -0.1250f, -28.8125f, 30.0000f, 32, 31}, // 878d + {0.866211f, 0.322266f, 0.881836f, 0.337402f, -0.1250f, -28.8125f, 30.0000f, 32, 31}, // 878d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 878e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 878f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8790 @@ -15876,7 +16177,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 879f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 87a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 87a1 - {0.800781f, 0.302734f, 0.815918f, 0.318359f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 87a2 + {0.937500f, 0.322266f, 0.952637f, 0.337891f, 0.0000f, -29.1875f, 30.0000f, 31, 32}, // 87a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 87a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 87a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 87a5 @@ -16034,47 +16335,47 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 883d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 883e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 883f - {0.981445f, 0.616211f, 0.996582f, 0.630371f, -0.3750f, -28.1875f, 30.0000f, 31, 29}, // 8840 + {0.227539f, 0.644531f, 0.242676f, 0.658691f, -0.3750f, -28.1875f, 30.0000f, 31, 29}, // 8840 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8841 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8842 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8843 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8844 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8845 - {0.161133f, 0.144043f, 0.176758f, 0.159668f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 8846 + {0.306152f, 0.160156f, 0.321777f, 0.175781f, -0.5625f, -29.1250f, 30.0000f, 32, 32}, // 8846 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8847 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8848 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8849 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 884a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 884b - {0.862305f, 0.302734f, 0.877441f, 0.318359f, -0.5000f, -29.3750f, 30.0000f, 31, 32}, // 884c + {0.348633f, 0.322754f, 0.363770f, 0.338379f, -0.5000f, -29.3750f, 30.0000f, 31, 32}, // 884c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 884d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 884e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 884f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8850 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8851 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8852 - {0.877930f, 0.302734f, 0.893555f, 0.317871f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 8853 + {0.395996f, 0.322754f, 0.411621f, 0.337891f, -0.8750f, -28.7500f, 30.0000f, 32, 31}, // 8853 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8854 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8855 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8856 - {0.193359f, 0.144043f, 0.208984f, 0.159668f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 8857 + {0.322266f, 0.160156f, 0.337891f, 0.175781f, -0.8125f, -29.0000f, 30.0000f, 32, 32}, // 8857 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8858 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8859 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 885a - {0.370605f, 0.144043f, 0.386230f, 0.159668f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 885b + {0.338379f, 0.160156f, 0.354004f, 0.175781f, -0.8750f, -29.1875f, 30.0000f, 32, 32}, // 885b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 885c - {0.386719f, 0.144043f, 0.402344f, 0.159668f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 885d + {0.257813f, 0.160645f, 0.273438f, 0.176270f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 885d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 885e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 885f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8860 - {0.680176f, 0.144043f, 0.695801f, 0.159668f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 8861 + {0.505859f, 0.161621f, 0.521484f, 0.177246f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 8861 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8862 - {0.527832f, 0.303223f, 0.543457f, 0.318359f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 8863 + {0.429688f, 0.322754f, 0.445313f, 0.337891f, -0.8750f, -28.8125f, 30.0000f, 32, 31}, // 8863 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8864 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8865 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8866 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8867 - {0.177246f, 0.144531f, 0.192871f, 0.160156f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 8868 + {0.521973f, 0.161621f, 0.537598f, 0.177246f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 8868 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8869 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 886a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 886b @@ -16082,14 +16383,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 886d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 886e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 886f - {0.556641f, 0.145020f, 0.572266f, 0.160645f, -0.9375f, -29.0000f, 30.0000f, 32, 32}, // 8870 + {0.804199f, 0.161621f, 0.819824f, 0.177246f, -0.9375f, -29.0000f, 30.0000f, 32, 32}, // 8870 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8871 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8872 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8873 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8874 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8875 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8876 - {0.572754f, 0.145020f, 0.588379f, 0.160645f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 8877 + {0.882813f, 0.163086f, 0.898438f, 0.178711f, -0.7500f, -28.8750f, 30.0000f, 32, 32}, // 8877 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8878 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8879 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 887a @@ -16109,7 +16410,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8888 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8889 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 888a - {0.588867f, 0.145020f, 0.604492f, 0.160645f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 888b + {0.370605f, 0.164551f, 0.386230f, 0.180176f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 888b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 888c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 888d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 888e @@ -16141,7 +16442,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88aa - {0.604980f, 0.145020f, 0.620605f, 0.160645f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 88ab + {0.434082f, 0.164551f, 0.449707f, 0.180176f, -0.9375f, -29.1875f, 30.0000f, 32, 32}, // 88ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88ae @@ -16163,11 +16464,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c0 - {0.621094f, 0.145020f, 0.636719f, 0.160645f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 88c1 - {0.637207f, 0.145020f, 0.652832f, 0.160645f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 88c2 + {0.450195f, 0.164551f, 0.465820f, 0.180176f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 88c1 + {0.466309f, 0.164551f, 0.481934f, 0.180176f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 88c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c4 - {0.592285f, 0.303223f, 0.607910f, 0.318359f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 88c5 + {0.529297f, 0.322754f, 0.544922f, 0.337891f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 88c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88c8 @@ -16177,20 +16478,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88ce - {0.714844f, 0.145020f, 0.730469f, 0.160645f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 88cf + {0.482422f, 0.164551f, 0.498047f, 0.180176f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 88cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d4 - {0.730957f, 0.145020f, 0.746582f, 0.160645f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 88d5 + {0.580566f, 0.164551f, 0.596191f, 0.180176f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 88d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88db - {0.608398f, 0.303223f, 0.624023f, 0.318359f, -1.0625f, -29.0625f, 30.0000f, 32, 31}, // 88dc + {0.412109f, 0.323242f, 0.427734f, 0.338379f, -1.0625f, -29.0625f, 30.0000f, 32, 31}, // 88dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88df @@ -16218,12 +16519,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88f7 - {0.768066f, 0.177246f, 0.784180f, 0.192383f, -0.8125f, -28.6875f, 30.0000f, 33, 31}, // 88f8 + {0.842773f, 0.197266f, 0.858887f, 0.212402f, -0.8125f, -28.6875f, 30.0000f, 33, 31}, // 88f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88fc - {0.077148f, 0.028809f, 0.093262f, 0.044434f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 88fd + {0.226074f, 0.044922f, 0.242188f, 0.060547f, -1.1875f, -29.3125f, 30.0000f, 33, 32}, // 88fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 88ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8900 @@ -16233,7 +16534,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8904 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8905 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8906 - {0.747070f, 0.145020f, 0.762695f, 0.160645f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 8907 + {0.921387f, 0.164551f, 0.937012f, 0.180176f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 8907 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8908 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8909 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 890a @@ -16242,9 +16543,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 890d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 890e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 890f - {0.333008f, 0.398926f, 0.348145f, 0.414063f, -0.9375f, -29.0625f, 30.0000f, 31, 31}, // 8910 + {0.492188f, 0.423340f, 0.507324f, 0.438477f, -0.9375f, -29.0625f, 30.0000f, 31, 31}, // 8910 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8911 - {0.763184f, 0.145020f, 0.778809f, 0.160645f, -0.3750f, -29.3125f, 30.0000f, 32, 32}, // 8912 + {0.937500f, 0.164551f, 0.953125f, 0.180176f, -0.3750f, -29.3125f, 30.0000f, 32, 32}, // 8912 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8913 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8914 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8915 @@ -16321,7 +16622,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 895c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 895d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 895e - {0.093750f, 0.028809f, 0.109863f, 0.044434f, -0.9375f, -29.0625f, 30.0000f, 33, 32}, // 895f + {0.193359f, 0.045410f, 0.209473f, 0.061035f, -0.9375f, -29.0625f, 30.0000f, 33, 32}, // 895f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8960 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8961 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8962 @@ -16340,7 +16641,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 896f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8970 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8971 - {0.673340f, 0.303223f, 0.688477f, 0.318848f, -0.5000f, -29.2500f, 30.0000f, 31, 32}, // 8972 + {0.898926f, 0.323242f, 0.914063f, 0.338867f, -0.5000f, -29.2500f, 30.0000f, 31, 32}, // 8972 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8973 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8974 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8975 @@ -16353,34 +16654,34 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 897c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 897d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 897e - {0.378418f, 0.647461f, 0.393066f, 0.661621f, 0.1875f, -27.1875f, 30.0000f, 30, 29}, // 897f + {0.925293f, 0.676270f, 0.939941f, 0.690430f, 0.1875f, -27.1875f, 30.0000f, 30, 29}, // 897f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8980 - {0.061523f, 0.534668f, 0.076660f, 0.549316f, -0.4375f, -27.4375f, 30.0000f, 31, 30}, // 8981 + {0.801758f, 0.557617f, 0.816895f, 0.572266f, -0.4375f, -27.4375f, 30.0000f, 31, 30}, // 8981 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8982 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8983 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8984 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8985 - {0.720703f, 0.303223f, 0.736328f, 0.318359f, -0.3750f, -28.5625f, 30.0000f, 32, 31}, // 8986 - {0.348633f, 0.398926f, 0.363770f, 0.414063f, -0.1250f, -28.5625f, 30.0000f, 31, 31}, // 8987 + {0.805176f, 0.324219f, 0.820801f, 0.339355f, -0.3750f, -28.5625f, 30.0000f, 32, 31}, // 8986 + {0.631836f, 0.423340f, 0.646973f, 0.438477f, -0.1250f, -28.5625f, 30.0000f, 31, 31}, // 8987 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8988 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8989 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 898a - {0.153320f, 0.534668f, 0.168457f, 0.549316f, -0.2500f, -27.5000f, 30.0000f, 31, 30}, // 898b + {0.891602f, 0.557617f, 0.906738f, 0.572266f, -0.2500f, -27.5000f, 30.0000f, 31, 30}, // 898b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 898c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 898d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 898e - {0.575684f, 0.303711f, 0.591309f, 0.318848f, -0.7500f, -28.3750f, 30.0000f, 32, 31}, // 898f + {0.837402f, 0.324219f, 0.853027f, 0.339355f, -0.7500f, -28.3750f, 30.0000f, 32, 31}, // 898f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8990 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8991 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8992 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8993 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8994 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8995 - {0.143555f, 0.304199f, 0.159180f, 0.319336f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 8996 + {0.882324f, 0.324219f, 0.897949f, 0.339355f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 8996 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8997 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8998 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8999 - {0.622559f, 0.398926f, 0.637695f, 0.414063f, -0.9375f, -28.5000f, 30.0000f, 31, 31}, // 899a + {0.680176f, 0.423340f, 0.695313f, 0.438477f, -0.9375f, -28.5000f, 30.0000f, 31, 31}, // 899a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 899b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 899c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 899d @@ -16393,10 +16694,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89a6 - {0.434570f, 0.304199f, 0.450195f, 0.319336f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 89a7 + {0.914551f, 0.324707f, 0.930176f, 0.339844f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 89a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89a9 - {0.543945f, 0.304199f, 0.559570f, 0.319336f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 89aa + {0.953125f, 0.324707f, 0.968750f, 0.339844f, -0.6250f, -28.8125f, 30.0000f, 32, 31}, // 89aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89ad @@ -16405,7 +16706,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b2 - {0.110352f, 0.028809f, 0.126465f, 0.044434f, -0.8750f, -29.2500f, 30.0000f, 33, 32}, // 89b3 + {0.819336f, 0.046875f, 0.835449f, 0.062500f, -0.8750f, -29.2500f, 30.0000f, 33, 32}, // 89b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89b6 @@ -16422,7 +16723,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c3 - {0.688965f, 0.304199f, 0.704590f, 0.319336f, -1.2500f, -28.8125f, 30.0000f, 32, 31}, // 89c4 + {0.969238f, 0.324707f, 0.984863f, 0.339844f, -1.2500f, -28.8125f, 30.0000f, 32, 31}, // 89c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89c7 @@ -16436,7 +16737,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89d1 - {0.181641f, 0.620117f, 0.195313f, 0.635742f, 0.0625f, -29.5000f, 30.0000f, 28, 32}, // 89d2 + {0.983398f, 0.652344f, 0.997070f, 0.667969f, 0.0625f, -29.5000f, 30.0000f, 28, 32}, // 89d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89d4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89d5 @@ -16453,10 +16754,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e2 - {0.705078f, 0.304199f, 0.720215f, 0.319824f, -0.5000f, -29.0625f, 30.0000f, 31, 32}, // 89e3 + {0.095703f, 0.325195f, 0.110840f, 0.340820f, -0.5000f, -29.0625f, 30.0000f, 31, 32}, // 89e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e5 - {0.779297f, 0.145020f, 0.794922f, 0.160645f, -0.9375f, -29.0000f, 30.0000f, 32, 32}, // 89e6 + {0.953613f, 0.164551f, 0.969238f, 0.180176f, -0.9375f, -29.0000f, 30.0000f, 32, 32}, // 89e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89e9 @@ -16474,7 +16775,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89f7 - {0.700195f, 0.446777f, 0.714844f, 0.462402f, -0.1250f, -29.0000f, 30.0000f, 30, 32}, // 89f8 + {0.647949f, 0.471680f, 0.662598f, 0.487305f, -0.1250f, -29.0000f, 30.0000f, 30, 32}, // 89f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89fb @@ -16482,38 +16783,38 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 89ff - {0.059570f, 0.616699f, 0.073730f, 0.631836f, 0.5000f, -28.5625f, 30.0000f, 29, 31}, // 8a00 + {0.365234f, 0.645508f, 0.379395f, 0.660645f, 0.5000f, -28.5625f, 30.0000f, 29, 31}, // 8a00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a01 - {0.654785f, 0.398926f, 0.669922f, 0.414063f, -0.2500f, -28.5000f, 30.0000f, 31, 31}, // 8a02 + {0.765625f, 0.423340f, 0.780762f, 0.438477f, -0.2500f, -28.5000f, 30.0000f, 31, 31}, // 8a02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a07 - {0.736816f, 0.304199f, 0.752441f, 0.319336f, -0.5000f, -29.0625f, 30.0000f, 32, 31}, // 8a08 + {0.364258f, 0.326172f, 0.379883f, 0.341309f, -0.5000f, -29.0625f, 30.0000f, 32, 31}, // 8a08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a09 - {0.752930f, 0.304199f, 0.768555f, 0.319336f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a0a + {0.623535f, 0.326172f, 0.639160f, 0.341309f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a0d - {0.769043f, 0.304199f, 0.784180f, 0.319824f, -0.1875f, -28.9375f, 30.0000f, 31, 32}, // 8a0e + {0.380371f, 0.326660f, 0.395508f, 0.342285f, -0.1875f, -28.9375f, 30.0000f, 31, 32}, // 8a0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a12 - {0.031250f, 0.535645f, 0.045898f, 0.550781f, -0.2500f, -28.8750f, 30.0000f, 30, 31}, // 8a13 + {0.311035f, 0.558594f, 0.325684f, 0.573730f, -0.2500f, -28.8750f, 30.0000f, 30, 31}, // 8a13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a16 - {0.702148f, 0.398926f, 0.717285f, 0.414063f, -0.2500f, -29.0625f, 30.0000f, 31, 31}, // 8a17 - {0.780762f, 0.398926f, 0.795898f, 0.414063f, -0.1875f, -28.7500f, 30.0000f, 31, 31}, // 8a18 + {0.205078f, 0.423828f, 0.220215f, 0.438965f, -0.2500f, -29.0625f, 30.0000f, 31, 31}, // 8a17 + {0.476074f, 0.423828f, 0.491211f, 0.438965f, -0.1875f, -28.7500f, 30.0000f, 31, 31}, // 8a18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a1e - {0.784668f, 0.304199f, 0.800293f, 0.319336f, -0.2500f, -28.4375f, 30.0000f, 32, 31}, // 8a1f + {0.656250f, 0.327637f, 0.671875f, 0.342773f, -0.2500f, -28.4375f, 30.0000f, 32, 31}, // 8a1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a22 @@ -16524,25 +16825,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a29 - {0.812988f, 0.398926f, 0.828125f, 0.414063f, -0.2500f, -28.7500f, 30.0000f, 31, 31}, // 8a2a + {0.526855f, 0.423828f, 0.541992f, 0.438965f, -0.2500f, -28.7500f, 30.0000f, 31, 31}, // 8a2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a2c - {0.846191f, 0.304199f, 0.861816f, 0.319336f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a2d + {0.320801f, 0.328125f, 0.336426f, 0.343262f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a30 - {0.894043f, 0.304199f, 0.909180f, 0.319824f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8a31 + {0.707031f, 0.326660f, 0.722168f, 0.342285f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8a31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a32 - {0.943359f, 0.304199f, 0.958984f, 0.319336f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a33 - {0.795410f, 0.145020f, 0.811035f, 0.160645f, -0.3125f, -29.1250f, 30.0000f, 32, 32}, // 8a34 + {0.789063f, 0.328125f, 0.804688f, 0.343262f, -0.2500f, -28.5000f, 30.0000f, 32, 31}, // 8a33 + {0.969727f, 0.164551f, 0.985352f, 0.180176f, -0.3125f, -29.1250f, 30.0000f, 32, 32}, // 8a34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a39 - {0.811523f, 0.145020f, 0.827148f, 0.160645f, -0.3125f, -29.3125f, 30.0000f, 32, 32}, // 8a3a + {0.859863f, 0.165039f, 0.875488f, 0.180664f, -0.3125f, -29.3125f, 30.0000f, 32, 32}, // 8a3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a3b - {0.876953f, 0.398926f, 0.892090f, 0.414063f, -0.4375f, -28.5000f, 30.0000f, 31, 31}, // 8a3c + {0.542480f, 0.423828f, 0.557617f, 0.438965f, -0.4375f, -28.5000f, 30.0000f, 31, 31}, // 8a3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a3f @@ -16562,12 +16863,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a4f - {0.959473f, 0.304199f, 0.974609f, 0.319824f, -0.1875f, -29.2500f, 30.0000f, 31, 32}, // 8a50 + {0.770020f, 0.328613f, 0.785156f, 0.344238f, -0.1875f, -29.2500f, 30.0000f, 31, 32}, // 8a50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a53 - {0.530273f, 0.535645f, 0.544922f, 0.550781f, -0.2500f, -28.5000f, 30.0000f, 30, 31}, // 8a54 - {0.975098f, 0.304199f, 0.990723f, 0.319336f, -0.4375f, -28.5000f, 30.0000f, 32, 31}, // 8a55 + {0.369629f, 0.558594f, 0.384277f, 0.573730f, -0.2500f, -28.5000f, 30.0000f, 30, 31}, // 8a54 + {0.492676f, 0.329102f, 0.508301f, 0.344238f, -0.4375f, -28.5000f, 30.0000f, 32, 31}, // 8a55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a58 @@ -16576,28 +16877,28 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a5d - {0.672363f, 0.536133f, 0.687012f, 0.551270f, -0.2500f, -28.5000f, 30.0000f, 30, 31}, // 8a5e + {0.836914f, 0.558594f, 0.851563f, 0.573730f, -0.2500f, -28.5000f, 30.0000f, 30, 31}, // 8a5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a5f - {0.845703f, 0.145020f, 0.861328f, 0.160645f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 8a60 + {0.898926f, 0.165527f, 0.914551f, 0.181152f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 8a60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a65 - {0.271973f, 0.304688f, 0.287598f, 0.319824f, -0.2500f, -28.9375f, 30.0000f, 32, 31}, // 8a66 + {0.689941f, 0.329102f, 0.705566f, 0.344238f, -0.2500f, -28.9375f, 30.0000f, 32, 31}, // 8a66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a68 - {0.365723f, 0.304688f, 0.380859f, 0.320313f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 8a69 + {0.191406f, 0.329590f, 0.206543f, 0.345215f, -0.2500f, -29.1875f, 30.0000f, 31, 32}, // 8a69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a6f - {0.892578f, 0.398926f, 0.907715f, 0.414063f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 8a70 - {0.497070f, 0.304688f, 0.512695f, 0.319824f, -0.4375f, -29.0625f, 30.0000f, 32, 31}, // 8a71 - {0.624512f, 0.304688f, 0.640137f, 0.319824f, -0.4375f, -28.7500f, 30.0000f, 32, 31}, // 8a72 - {0.450684f, 0.304688f, 0.465820f, 0.320313f, -0.2500f, -29.3125f, 30.0000f, 31, 32}, // 8a73 + {0.664063f, 0.423828f, 0.679199f, 0.438965f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 8a70 + {0.207031f, 0.329590f, 0.222656f, 0.344727f, -0.4375f, -29.0625f, 30.0000f, 32, 31}, // 8a71 + {0.508789f, 0.329590f, 0.524414f, 0.344727f, -0.4375f, -28.7500f, 30.0000f, 32, 31}, // 8a72 + {0.545410f, 0.329590f, 0.560547f, 0.345215f, -0.2500f, -29.3125f, 30.0000f, 31, 32}, // 8a73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a76 @@ -16617,36 +16918,36 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a86 - {0.861816f, 0.145020f, 0.877441f, 0.160645f, -0.1875f, -29.3125f, 30.0000f, 32, 32}, // 8a87 + {0.096680f, 0.166504f, 0.112305f, 0.182129f, -0.1875f, -29.3125f, 30.0000f, 32, 32}, // 8a87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a88 - {0.877930f, 0.145020f, 0.893555f, 0.160645f, -0.7500f, -29.3125f, 30.0000f, 32, 32}, // 8a89 + {0.112793f, 0.166504f, 0.128418f, 0.182129f, -0.7500f, -29.3125f, 30.0000f, 32, 32}, // 8a89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a8b - {0.816406f, 0.304688f, 0.832031f, 0.319824f, -0.4375f, -28.6250f, 30.0000f, 32, 31}, // 8a8c - {0.874023f, 0.446777f, 0.889648f, 0.461426f, -0.4375f, -28.3750f, 30.0000f, 32, 30}, // 8a8d + {0.639648f, 0.329590f, 0.655273f, 0.344727f, -0.4375f, -28.6250f, 30.0000f, 32, 31}, // 8a8c + {0.062500f, 0.472656f, 0.078125f, 0.487305f, -0.4375f, -28.3750f, 30.0000f, 32, 30}, // 8a8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a92 - {0.909668f, 0.304688f, 0.924805f, 0.320313f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 8a93 + {0.561035f, 0.329590f, 0.576172f, 0.345215f, -0.0625f, -29.1875f, 30.0000f, 31, 32}, // 8a93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a94 - {0.925293f, 0.304688f, 0.940918f, 0.319824f, -0.2500f, -28.5625f, 30.0000f, 32, 31}, // 8a95 + {0.672363f, 0.330078f, 0.687988f, 0.345215f, -0.2500f, -28.5625f, 30.0000f, 32, 31}, // 8a95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a97 - {0.240723f, 0.305176f, 0.256348f, 0.320313f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8a98 + {0.047852f, 0.330566f, 0.063477f, 0.345703f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8a98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a9d - {0.657227f, 0.305176f, 0.672852f, 0.320313f, -0.5625f, -28.4375f, 30.0000f, 32, 31}, // 8a9e + {0.576660f, 0.330566f, 0.592285f, 0.345703f, -0.5625f, -28.4375f, 30.0000f, 32, 31}, // 8a9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8a9f - {0.894043f, 0.145020f, 0.909668f, 0.160645f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 8aa0 + {0.128906f, 0.166992f, 0.144531f, 0.182617f, -0.5000f, -29.0000f, 30.0000f, 32, 32}, // 8aa0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa3 - {0.188477f, 0.399414f, 0.203613f, 0.414551f, -0.2500f, -28.4375f, 30.0000f, 31, 31}, // 8aa4 + {0.046875f, 0.424316f, 0.062012f, 0.439453f, -0.2500f, -28.4375f, 30.0000f, 31, 31}, // 8aa4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa7 @@ -16654,13 +16955,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aa9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aaa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aab - {0.256836f, 0.305176f, 0.271973f, 0.320801f, -0.2500f, -29.4375f, 30.0000f, 31, 32}, // 8aac - {0.191406f, 0.305664f, 0.207031f, 0.320801f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8aad + {0.592773f, 0.330566f, 0.607910f, 0.346191f, -0.2500f, -29.4375f, 30.0000f, 31, 32}, // 8aac + {0.079102f, 0.331055f, 0.094727f, 0.346191f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8aad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aaf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ab0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ab1 - {0.224121f, 0.306152f, 0.239746f, 0.321289f, -0.3125f, -28.5000f, 30.0000f, 32, 31}, // 8ab2 + {0.142578f, 0.331055f, 0.158203f, 0.346191f, -0.3125f, -28.5000f, 30.0000f, 32, 31}, // 8ab2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ab3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ab4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ab5 @@ -16673,7 +16974,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8abc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8abd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8abe - {0.703613f, 0.536133f, 0.718262f, 0.551270f, -0.4375f, -28.5000f, 30.0000f, 30, 31}, // 8abf + {0.971191f, 0.559082f, 0.985840f, 0.574219f, -0.4375f, -28.5000f, 30.0000f, 30, 31}, // 8abf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac2 @@ -16681,11 +16982,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac6 - {0.417969f, 0.306152f, 0.433105f, 0.321777f, -0.1250f, -29.2500f, 30.0000f, 31, 32}, // 8ac7 + {0.158691f, 0.331055f, 0.173828f, 0.346680f, -0.1250f, -29.2500f, 30.0000f, 31, 32}, // 8ac7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ac9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aca - {0.910156f, 0.145020f, 0.925781f, 0.160645f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 8acb + {0.746094f, 0.166992f, 0.761719f, 0.182617f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 8acb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8acc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8acd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ace @@ -16696,7 +16997,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad5 - {0.926270f, 0.145020f, 0.941895f, 0.160645f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 8ad6 + {0.386719f, 0.167480f, 0.402344f, 0.183105f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 8ad6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ad9 @@ -16719,8 +17020,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aeb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aec - {0.942383f, 0.145020f, 0.958008f, 0.160645f, -0.5625f, -29.5625f, 30.0000f, 32, 32}, // 8aed - {0.958496f, 0.145020f, 0.974121f, 0.160645f, -0.4375f, -29.3750f, 30.0000f, 32, 32}, // 8aee + {0.402832f, 0.167480f, 0.418457f, 0.183105f, -0.5625f, -29.5625f, 30.0000f, 32, 32}, // 8aed + {0.661621f, 0.167480f, 0.677246f, 0.183105f, -0.4375f, -29.3750f, 30.0000f, 32, 32}, // 8aee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af1 @@ -16730,19 +17031,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af7 - {0.466309f, 0.306152f, 0.481445f, 0.321777f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8af8 + {0.608398f, 0.331055f, 0.623535f, 0.346680f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8af8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8af9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8afa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8afb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8afc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8afd - {0.481934f, 0.306152f, 0.497070f, 0.321777f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 8afe + {0.063965f, 0.331543f, 0.079102f, 0.347168f, -0.4375f, -29.0625f, 30.0000f, 31, 32}, // 8afe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8aff - {0.207520f, 0.306641f, 0.223145f, 0.321777f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8b00 - {0.545410f, 0.536621f, 0.560059f, 0.551758f, -0.1250f, -28.5000f, 30.0000f, 30, 31}, // 8b01 + {0.111328f, 0.332031f, 0.126953f, 0.347168f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8b00 + {0.591797f, 0.559570f, 0.606445f, 0.574707f, -0.1250f, -28.5000f, 30.0000f, 30, 31}, // 8b01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b03 - {0.974609f, 0.145020f, 0.990234f, 0.160645f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 8b04 + {0.354492f, 0.168945f, 0.370117f, 0.184570f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 8b04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b07 @@ -16763,15 +17064,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b18 - {0.523926f, 0.145508f, 0.539551f, 0.161133f, -0.0625f, -29.3125f, 30.0000f, 32, 32}, // 8b19 + {0.695313f, 0.168945f, 0.710938f, 0.184570f, -0.0625f, -29.3125f, 30.0000f, 32, 32}, // 8b19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b1a - {0.429199f, 0.399414f, 0.444336f, 0.414551f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 8b1b + {0.174316f, 0.424316f, 0.189453f, 0.439453f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 8b1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b1c - {0.333496f, 0.308594f, 0.348633f, 0.324219f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 8b1d + {0.174316f, 0.332031f, 0.189453f, 0.347656f, -0.4375f, -29.3750f, 30.0000f, 31, 32}, // 8b1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b20 - {0.381348f, 0.311523f, 0.396973f, 0.326660f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8b21 + {0.000000f, 0.333008f, 0.015625f, 0.348145f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8b21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b24 @@ -16795,7 +17096,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b38 - {0.477539f, 0.399414f, 0.492676f, 0.414551f, -0.2500f, -28.8750f, 30.0000f, 31, 31}, // 8b39 + {0.189941f, 0.424316f, 0.205078f, 0.439453f, -0.2500f, -28.8750f, 30.0000f, 31, 31}, // 8b39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b3c @@ -16826,11 +17127,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b57 - {0.653320f, 0.145508f, 0.668945f, 0.161133f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 8b58 + {0.820313f, 0.168945f, 0.835938f, 0.184570f, -0.5000f, -29.0625f, 30.0000f, 32, 32}, // 8b58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b5b - {0.827637f, 0.145508f, 0.843262f, 0.161133f, -0.4375f, -29.3125f, 30.0000f, 32, 32}, // 8b5c + {0.836426f, 0.169434f, 0.852051f, 0.185059f, -0.4375f, -29.3125f, 30.0000f, 32, 32}, // 8b5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b5f @@ -16840,7 +17141,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b65 - {0.111816f, 0.312012f, 0.126953f, 0.327637f, -0.3750f, -28.7500f, 30.0000f, 31, 32}, // 8b66 + {0.127441f, 0.332520f, 0.142578f, 0.348145f, -0.3750f, -28.7500f, 30.0000f, 31, 32}, // 8b66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b69 @@ -16849,15 +17150,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b6e - {0.168945f, 0.537109f, 0.184082f, 0.551758f, -0.4375f, -27.8750f, 30.0000f, 31, 30}, // 8b6f - {0.540039f, 0.145996f, 0.555664f, 0.161621f, -0.3750f, -29.5625f, 30.0000f, 32, 32}, // 8b70 + {0.672363f, 0.559570f, 0.687500f, 0.574219f, -0.4375f, -27.8750f, 30.0000f, 31, 30}, // 8b6f + {0.209473f, 0.170898f, 0.225098f, 0.186523f, -0.3750f, -29.5625f, 30.0000f, 32, 32}, // 8b70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b71 - {0.273926f, 0.146484f, 0.289551f, 0.162109f, -0.4375f, -29.1250f, 30.0000f, 32, 32}, // 8b72 + {0.225586f, 0.170898f, 0.241211f, 0.186523f, -0.4375f, -29.1250f, 30.0000f, 32, 32}, // 8b72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b73 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b76 - {0.397461f, 0.312012f, 0.413086f, 0.327148f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 8b77 + {0.016113f, 0.333008f, 0.031738f, 0.348145f, -0.4375f, -29.1250f, 30.0000f, 32, 31}, // 8b77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b7a @@ -16866,7 +17167,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b7f - {0.290039f, 0.146484f, 0.305664f, 0.162109f, -0.2500f, -29.0625f, 30.0000f, 32, 32}, // 8b80 + {0.241699f, 0.170898f, 0.257324f, 0.186523f, -0.2500f, -29.0625f, 30.0000f, 32, 32}, // 8b80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b83 @@ -16899,10 +17200,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8b9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba0 - {0.890137f, 0.446777f, 0.904785f, 0.462402f, 0.1875f, -29.1875f, 30.0000f, 30, 32}, // 8ba1 + {0.172363f, 0.472168f, 0.187012f, 0.487793f, 0.1875f, -29.1875f, 30.0000f, 30, 32}, // 8ba1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba3 - {0.252441f, 0.399902f, 0.267578f, 0.415039f, 0.1250f, -28.8125f, 30.0000f, 31, 31}, // 8ba4 + {0.558105f, 0.424316f, 0.573242f, 0.439453f, 0.1250f, -28.8125f, 30.0000f, 31, 31}, // 8ba4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ba7 @@ -16912,9 +17213,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bad - {0.000000f, 0.312988f, 0.015625f, 0.328125f, -0.5625f, -28.2500f, 30.0000f, 32, 31}, // 8bae + {0.738281f, 0.333496f, 0.753906f, 0.348633f, -0.5625f, -28.2500f, 30.0000f, 32, 31}, // 8bae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8baf - {0.952637f, 0.587402f, 0.967285f, 0.602051f, 0.3750f, -29.0625f, 30.0000f, 30, 30}, // 8bb0 + {0.806641f, 0.618164f, 0.821289f, 0.632813f, 0.3750f, -29.0625f, 30.0000f, 30, 30}, // 8bb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb3 @@ -16922,21 +17223,21 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb7 - {0.288086f, 0.312988f, 0.303223f, 0.328613f, -0.1250f, -29.1250f, 30.0000f, 31, 32}, // 8bb8 + {0.223145f, 0.333984f, 0.238281f, 0.349609f, -0.1250f, -29.1250f, 30.0000f, 31, 32}, // 8bb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bb9 - {0.392090f, 0.447266f, 0.407715f, 0.461914f, -0.4375f, -28.8750f, 30.0000f, 32, 30}, // 8bba + {0.155762f, 0.473145f, 0.171387f, 0.487793f, -0.4375f, -28.8750f, 30.0000f, 32, 30}, // 8bba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bbd - {0.482910f, 0.537109f, 0.498047f, 0.551758f, -0.3750f, -28.1875f, 30.0000f, 31, 30}, // 8bbe - {0.218750f, 0.447266f, 0.233398f, 0.462891f, 0.1250f, -29.4375f, 30.0000f, 30, 32}, // 8bbf + {0.852051f, 0.560059f, 0.867188f, 0.574707f, -0.3750f, -28.1875f, 30.0000f, 31, 30}, // 8bbe + {0.553711f, 0.472168f, 0.568359f, 0.487793f, 0.1250f, -29.4375f, 30.0000f, 30, 32}, // 8bbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc0 - {0.196777f, 0.616699f, 0.211914f, 0.630859f, -0.3125f, -27.9375f, 30.0000f, 31, 29}, // 8bc1 + {0.379883f, 0.645508f, 0.395020f, 0.659668f, -0.3125f, -27.9375f, 30.0000f, 31, 29}, // 8bc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc5 - {0.440430f, 0.447266f, 0.456055f, 0.461914f, -0.5625f, -28.3750f, 30.0000f, 32, 30}, // 8bc6 + {0.000000f, 0.473633f, 0.015625f, 0.488281f, -0.5625f, -28.3750f, 30.0000f, 32, 30}, // 8bc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bc9 @@ -16947,11 +17248,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bcf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd0 - {0.204102f, 0.400391f, 0.219238f, 0.415527f, -0.1875f, -28.5000f, 30.0000f, 31, 31}, // 8bd1 + {0.142090f, 0.424805f, 0.157227f, 0.439941f, -0.1875f, -28.5000f, 30.0000f, 31, 31}, // 8bd1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd4 - {0.219727f, 0.400391f, 0.234863f, 0.415527f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 8bd5 + {0.573730f, 0.424805f, 0.588867f, 0.439941f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 8bd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bd8 @@ -16967,7 +17268,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be4 - {0.016113f, 0.314453f, 0.031250f, 0.330078f, 0.0625f, -29.1250f, 30.0000f, 31, 32}, // 8be5 + {0.271484f, 0.333984f, 0.286621f, 0.349609f, 0.0625f, -29.1250f, 30.0000f, 31, 32}, // 8be5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8be8 @@ -16975,9 +17276,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8beb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bec - {0.560547f, 0.537109f, 0.575684f, 0.551758f, -0.4375f, -27.8750f, 30.0000f, 31, 30}, // 8bed + {0.867676f, 0.560547f, 0.882813f, 0.575195f, -0.4375f, -27.8750f, 30.0000f, 31, 30}, // 8bed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bee - {0.576172f, 0.537109f, 0.591309f, 0.551758f, -0.1875f, -27.8125f, 30.0000f, 31, 30}, // 8bef + {0.326172f, 0.561035f, 0.341309f, 0.575684f, -0.1875f, -27.8125f, 30.0000f, 31, 30}, // 8bef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf2 @@ -16985,11 +17286,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf6 - {0.395996f, 0.400391f, 0.411133f, 0.415527f, -0.1875f, -28.9375f, 30.0000f, 31, 31}, // 8bf7 + {0.078125f, 0.425293f, 0.093262f, 0.440430f, -0.1875f, -28.9375f, 30.0000f, 31, 31}, // 8bf7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bfa - {0.063477f, 0.314941f, 0.078613f, 0.330566f, -0.3750f, -29.1250f, 30.0000f, 31, 32}, // 8bfb + {0.287109f, 0.333984f, 0.302246f, 0.349609f, -0.3750f, -29.1250f, 30.0000f, 31, 32}, // 8bfb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8bfe @@ -16997,7 +17298,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c02 - {0.617188f, 0.616699f, 0.631348f, 0.631836f, 0.1250f, -28.3125f, 30.0000f, 29, 31}, // 8c03 + {0.561523f, 0.645508f, 0.575684f, 0.660645f, 0.1250f, -28.3125f, 30.0000f, 29, 31}, // 8c03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c06 @@ -17028,7 +17329,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c21 - {0.079102f, 0.314941f, 0.094238f, 0.330566f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 8c22 + {0.722656f, 0.333984f, 0.737793f, 0.349609f, -0.4375f, -29.2500f, 30.0000f, 31, 32}, // 8c22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c25 @@ -17049,7 +17350,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c36 - {0.784668f, 0.177246f, 0.800781f, 0.192383f, -1.0000f, -29.1875f, 30.0000f, 33, 31}, // 8c37 + {0.885254f, 0.197754f, 0.901367f, 0.212891f, -1.0000f, -29.1875f, 30.0000f, 33, 31}, // 8c37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c3a @@ -17064,11 +17365,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c45 - {0.812012f, 0.676758f, 0.826172f, 0.690430f, 1.0000f, -27.3750f, 30.0000f, 29, 28}, // 8c46 + {0.419434f, 0.714355f, 0.433594f, 0.728027f, 1.0000f, -27.3750f, 30.0000f, 29, 28}, // 8c46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c49 - {0.640625f, 0.537109f, 0.655762f, 0.551758f, -0.3125f, -28.7500f, 30.0000f, 31, 30}, // 8c4a + {0.106934f, 0.562012f, 0.122070f, 0.576660f, -0.3125f, -28.7500f, 30.0000f, 31, 30}, // 8c4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c4d @@ -17084,14 +17385,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c59 - {0.671387f, 0.351074f, 0.687500f, 0.365723f, -1.1250f, -27.6875f, 30.0000f, 33, 30}, // 8c5a + {0.916992f, 0.370605f, 0.933105f, 0.385254f, -1.1250f, -27.6875f, 30.0000f, 33, 30}, // 8c5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c60 - {0.031738f, 0.315430f, 0.046875f, 0.331055f, 0.0000f, -29.3750f, 30.0000f, 31, 32}, // 8c61 + {0.238770f, 0.334473f, 0.253906f, 0.350098f, 0.0000f, -29.3750f, 30.0000f, 31, 32}, // 8c61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c64 @@ -17100,7 +17401,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c69 - {0.047363f, 0.315918f, 0.062500f, 0.331543f, 0.6250f, -29.0625f, 30.0000f, 31, 32}, // 8c6a + {0.254395f, 0.335449f, 0.269531f, 0.351074f, 0.6250f, -29.0625f, 30.0000f, 31, 32}, // 8c6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c6b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c6d @@ -17151,52 +17452,52 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c9c - {0.693359f, 0.647461f, 0.707520f, 0.662109f, 0.6250f, -27.6875f, 30.0000f, 29, 30}, // 8c9d - {0.303711f, 0.316895f, 0.318848f, 0.332520f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8c9e + {0.940430f, 0.676270f, 0.954590f, 0.690918f, 0.6250f, -27.6875f, 30.0000f, 29, 30}, // 8c9d + {0.032227f, 0.335938f, 0.047363f, 0.351563f, -0.2500f, -29.1250f, 30.0000f, 31, 32}, // 8c9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8c9f - {0.306152f, 0.146484f, 0.321777f, 0.162109f, -0.4375f, -29.6875f, 30.0000f, 32, 32}, // 8ca0 - {0.159668f, 0.317871f, 0.174805f, 0.333496f, -0.6875f, -28.8750f, 30.0000f, 31, 32}, // 8ca1 - {0.755859f, 0.537109f, 0.770996f, 0.551758f, -0.2500f, -27.6875f, 30.0000f, 31, 30}, // 8ca2 + {0.538086f, 0.170898f, 0.553711f, 0.186523f, -0.4375f, -29.6875f, 30.0000f, 32, 32}, // 8ca0 + {0.445801f, 0.335938f, 0.460938f, 0.351563f, -0.6875f, -28.8750f, 30.0000f, 31, 32}, // 8ca1 + {0.623047f, 0.562012f, 0.638184f, 0.576660f, -0.2500f, -27.6875f, 30.0000f, 31, 30}, // 8ca2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ca3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ca4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ca5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ca6 - {0.175293f, 0.318359f, 0.190918f, 0.333496f, -0.4375f, -28.7500f, 30.0000f, 32, 31}, // 8ca7 - {0.463867f, 0.146484f, 0.479492f, 0.162109f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 8ca8 - {0.297363f, 0.450684f, 0.312988f, 0.465332f, -0.5625f, -27.6875f, 30.0000f, 32, 30}, // 8ca9 + {0.461426f, 0.336426f, 0.477051f, 0.351563f, -0.4375f, -28.7500f, 30.0000f, 32, 31}, // 8ca7 + {0.554199f, 0.170898f, 0.569824f, 0.186523f, -0.5000f, -28.9375f, 30.0000f, 32, 32}, // 8ca8 + {0.109375f, 0.473633f, 0.125000f, 0.488281f, -0.5625f, -27.6875f, 30.0000f, 32, 30}, // 8ca9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8caa - {0.418457f, 0.537598f, 0.433594f, 0.552246f, -0.3125f, -27.5625f, 30.0000f, 31, 30}, // 8cab - {0.349121f, 0.318359f, 0.364258f, 0.333984f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 8cac + {0.770996f, 0.562012f, 0.786133f, 0.576660f, -0.3125f, -27.5625f, 30.0000f, 31, 30}, // 8cab + {0.477539f, 0.336426f, 0.492676f, 0.352051f, -0.3125f, -29.1250f, 30.0000f, 31, 32}, // 8cac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cae - {0.560059f, 0.318359f, 0.575684f, 0.333496f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 8caf + {0.754395f, 0.336426f, 0.770020f, 0.351563f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 8caf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb3 - {0.640625f, 0.318359f, 0.655762f, 0.333984f, -0.3125f, -29.0000f, 30.0000f, 31, 32}, // 8cb4 + {0.302734f, 0.336914f, 0.317871f, 0.352539f, -0.3125f, -29.0000f, 30.0000f, 31, 32}, // 8cb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb6 - {0.787109f, 0.537598f, 0.802246f, 0.552246f, -0.0625f, -27.5000f, 30.0000f, 31, 30}, // 8cb7 - {0.877930f, 0.318359f, 0.893066f, 0.333984f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 8cb8 + {0.091309f, 0.562500f, 0.106445f, 0.577148f, -0.0625f, -27.5000f, 30.0000f, 31, 30}, // 8cb7 + {0.821289f, 0.336914f, 0.836426f, 0.352539f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 8cb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cba - {0.203613f, 0.448242f, 0.218262f, 0.463867f, 0.1250f, -29.1250f, 30.0000f, 30, 32}, // 8cbb - {0.094727f, 0.318848f, 0.110352f, 0.333984f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 8cbc + {0.584473f, 0.472168f, 0.599121f, 0.487793f, 0.1250f, -29.1250f, 30.0000f, 30, 32}, // 8cbb + {0.853516f, 0.337891f, 0.869141f, 0.353027f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 8cbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cbe - {0.444824f, 0.400391f, 0.459961f, 0.415527f, 0.1250f, -28.8750f, 30.0000f, 31, 31}, // 8cbf - {0.127441f, 0.318848f, 0.142578f, 0.334473f, -0.0625f, -29.2500f, 30.0000f, 31, 32}, // 8cc0 + {0.589355f, 0.425293f, 0.604492f, 0.440430f, 0.1250f, -28.8750f, 30.0000f, 31, 31}, // 8cbf + {0.395996f, 0.338379f, 0.411133f, 0.354004f, -0.0625f, -29.2500f, 30.0000f, 31, 32}, // 8cc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc2 - {0.479980f, 0.146484f, 0.495605f, 0.162109f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 8cc3 - {0.447266f, 0.146973f, 0.462891f, 0.162598f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 8cc4 + {0.677734f, 0.171387f, 0.693359f, 0.187012f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 8cc3 + {0.711426f, 0.171387f, 0.727051f, 0.187012f, -0.3750f, -29.0000f, 30.0000f, 32, 32}, // 8cc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc6 - {0.513184f, 0.318848f, 0.528320f, 0.334473f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 8cc7 + {0.428223f, 0.338379f, 0.443359f, 0.354004f, -0.1875f, -29.1250f, 30.0000f, 31, 32}, // 8cc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cc9 - {0.591797f, 0.318848f, 0.607422f, 0.333984f, -0.8125f, -29.1250f, 30.0000f, 32, 31}, // 8cca + {0.524902f, 0.338379f, 0.540527f, 0.353516f, -0.8125f, -29.1250f, 30.0000f, 32, 31}, // 8cca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ccb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ccc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ccd @@ -17205,7 +17506,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd2 - {0.696289f, 0.146973f, 0.711914f, 0.162598f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 8cd3 + {0.727539f, 0.171387f, 0.743164f, 0.187012f, -0.6875f, -29.1250f, 30.0000f, 32, 32}, // 8cd3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd6 @@ -17213,22 +17514,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cda - {0.496094f, 0.147949f, 0.511719f, 0.163574f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 8cdb - {0.444336f, 0.587891f, 0.458984f, 0.602539f, -0.2500f, -27.7500f, 30.0000f, 30, 30}, // 8cdc + {0.596680f, 0.171875f, 0.612305f, 0.187500f, -0.5000f, -29.3125f, 30.0000f, 32, 32}, // 8cdb + {0.907227f, 0.618164f, 0.921875f, 0.632813f, -0.2500f, -27.7500f, 30.0000f, 30, 30}, // 8cdc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cdd - {0.528809f, 0.318848f, 0.543945f, 0.334473f, 0.1250f, -29.1250f, 30.0000f, 31, 32}, // 8cde + {0.930664f, 0.338379f, 0.945801f, 0.354004f, 0.1250f, -29.1250f, 30.0000f, 31, 32}, // 8cde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cdf - {0.607910f, 0.318848f, 0.623047f, 0.334473f, -0.2500f, -29.0625f, 30.0000f, 31, 32}, // 8ce0 + {0.336914f, 0.338867f, 0.352051f, 0.354492f, -0.2500f, -29.0625f, 30.0000f, 31, 32}, // 8ce0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce1 - {0.832520f, 0.537598f, 0.847656f, 0.552246f, 0.0625f, -27.6875f, 30.0000f, 31, 30}, // 8ce2 + {0.276367f, 0.562500f, 0.291504f, 0.577148f, 0.0625f, -27.6875f, 30.0000f, 31, 30}, // 8ce2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce5 - {0.209473f, 0.148438f, 0.225098f, 0.164063f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 8ce6 + {0.612793f, 0.171875f, 0.628418f, 0.187500f, -0.7500f, -29.1250f, 30.0000f, 32, 32}, // 8ce6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ce9 - {0.720703f, 0.318848f, 0.735840f, 0.334473f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 8cea + {0.411621f, 0.338867f, 0.426758f, 0.354492f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 8cea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ceb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ced @@ -17246,7 +17547,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cfa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cfb - {0.800781f, 0.318848f, 0.816406f, 0.333984f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 8cfc + {0.898438f, 0.339355f, 0.914063f, 0.354492f, -0.8125f, -28.8750f, 30.0000f, 32, 31}, // 8cfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8cff @@ -17258,7 +17559,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d07 - {0.862305f, 0.318848f, 0.877441f, 0.334473f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 8d08 + {0.805176f, 0.339844f, 0.820313f, 0.355469f, -1.0000f, -29.1250f, 30.0000f, 31, 32}, // 8d08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d0b @@ -17279,7 +17580,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d1c - {0.753906f, 0.647461f, 0.768066f, 0.662109f, 0.3125f, -27.8750f, 30.0000f, 29, 30}, // 8d1d + {0.360840f, 0.677246f, 0.375000f, 0.691895f, 0.3125f, -27.8750f, 30.0000f, 29, 30}, // 8d1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d20 @@ -17287,27 +17588,27 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d24 - {0.576172f, 0.319336f, 0.591309f, 0.334961f, -0.6250f, -29.0625f, 30.0000f, 31, 32}, // 8d25 + {0.836914f, 0.339844f, 0.852051f, 0.355469f, -0.6250f, -29.0625f, 30.0000f, 31, 32}, // 8d25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d27 - {0.673340f, 0.319336f, 0.688477f, 0.334961f, -1.3125f, -28.9375f, 30.0000f, 31, 32}, // 8d28 + {0.869629f, 0.339844f, 0.884766f, 0.355469f, -1.3125f, -28.9375f, 30.0000f, 31, 32}, // 8d28 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d2c - {0.460449f, 0.400391f, 0.475586f, 0.415527f, -1.0625f, -28.9375f, 30.0000f, 31, 31}, // 8d2d + {0.062500f, 0.425781f, 0.077637f, 0.440918f, -1.0625f, -28.9375f, 30.0000f, 31, 31}, // 8d2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d2f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d33 - {0.143066f, 0.319824f, 0.158203f, 0.335449f, -0.7500f, -29.0000f, 30.0000f, 31, 32}, // 8d34 + {0.914551f, 0.340332f, 0.929688f, 0.355957f, -0.7500f, -29.0000f, 30.0000f, 31, 32}, // 8d34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d37 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d38 - {0.293457f, 0.538086f, 0.308105f, 0.553223f, -0.2500f, -28.9375f, 30.0000f, 30, 31}, // 8d39 + {0.341797f, 0.562500f, 0.356445f, 0.577637f, -0.2500f, -28.9375f, 30.0000f, 30, 31}, // 8d39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d3c @@ -17350,9 +17651,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d63 - {0.108887f, 0.452148f, 0.123535f, 0.467773f, 0.0000f, -28.9375f, 30.0000f, 30, 32}, // 8d64 + {0.125488f, 0.473633f, 0.140137f, 0.489258f, 0.0000f, -28.9375f, 30.0000f, 30, 32}, // 8d64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d65 - {0.225586f, 0.148438f, 0.241211f, 0.164063f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 8d66 + {0.048340f, 0.172363f, 0.063965f, 0.187988f, -0.3750f, -29.5000f, 30.0000f, 32, 32}, // 8d66 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d67 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d68 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d69 @@ -17362,14 +17663,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d6f - {0.241699f, 0.148438f, 0.257324f, 0.164063f, -0.6875f, -28.9375f, 30.0000f, 32, 32}, // 8d70 + {0.064453f, 0.172363f, 0.080078f, 0.187988f, -0.6875f, -28.9375f, 30.0000f, 32, 32}, // 8d70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d73 - {0.257813f, 0.148438f, 0.273438f, 0.164063f, -0.8125f, -28.8750f, 30.0000f, 32, 32}, // 8d74 + {0.080566f, 0.172363f, 0.096191f, 0.187988f, -0.8125f, -28.8750f, 30.0000f, 32, 32}, // 8d74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d76 - {0.354492f, 0.149902f, 0.370117f, 0.165527f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 8d77 + {0.628906f, 0.172852f, 0.644531f, 0.188477f, -0.9375f, -29.0625f, 30.0000f, 32, 32}, // 8d77 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d78 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d79 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d7a @@ -17383,12 +17684,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d84 - {0.402832f, 0.152832f, 0.418457f, 0.168457f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 8d85 + {0.645020f, 0.172852f, 0.660645f, 0.188477f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 8d85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d89 - {0.418945f, 0.153320f, 0.434570f, 0.168945f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 8d8a + {0.145020f, 0.173828f, 0.160645f, 0.189453f, -0.7500f, -29.0000f, 30.0000f, 32, 32}, // 8d8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8d8d @@ -17413,7 +17714,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da2 - {0.433594f, 0.319824f, 0.449219f, 0.334961f, -1.1250f, -29.0625f, 30.0000f, 32, 31}, // 8da3 + {0.946289f, 0.340332f, 0.961914f, 0.355469f, -1.1250f, -29.0625f, 30.0000f, 32, 31}, // 8da3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8da6 @@ -17429,7 +17730,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db2 - {0.345703f, 0.452148f, 0.361328f, 0.466797f, -0.3750f, -26.8750f, 30.0000f, 32, 30}, // 8db3 + {0.251953f, 0.474121f, 0.267578f, 0.488770f, -0.3750f, -26.8750f, 30.0000f, 32, 30}, // 8db3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8db6 @@ -17471,11 +17772,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8dda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ddb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ddc - {0.361816f, 0.452637f, 0.377441f, 0.467285f, -1.1250f, -27.8750f, 30.0000f, 32, 30}, // 8ddd + {0.268066f, 0.474609f, 0.283691f, 0.489258f, -1.1250f, -27.8750f, 30.0000f, 32, 30}, // 8ddd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8dde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ddf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8de0 - {0.544434f, 0.319824f, 0.560059f, 0.334961f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 8de1 + {0.962402f, 0.340332f, 0.978027f, 0.355469f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 8de1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8de2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8de3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8de4 @@ -17489,13 +17790,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8dec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ded {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8dee - {0.185059f, 0.031250f, 0.201172f, 0.046875f, -1.1250f, -29.1250f, 30.0000f, 33, 32}, // 8def + {0.835938f, 0.046875f, 0.852051f, 0.062500f, -1.1250f, -29.1250f, 30.0000f, 33, 32}, // 8def {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df2 - {0.688965f, 0.319824f, 0.704590f, 0.334961f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 8df3 + {0.978516f, 0.340332f, 0.994141f, 0.355469f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 8df3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df4 - {0.736328f, 0.319824f, 0.751953f, 0.334961f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 8df5 + {0.095215f, 0.341309f, 0.110840f, 0.356445f, -0.8125f, -28.8125f, 30.0000f, 32, 31}, // 8df5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8df8 @@ -17516,12 +17817,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e09 - {0.874512f, 0.587891f, 0.889160f, 0.602539f, -0.5000f, -28.0000f, 30.0000f, 30, 30}, // 8e0a + {0.486328f, 0.618652f, 0.500977f, 0.633301f, -0.5000f, -28.0000f, 30.0000f, 30, 30}, // 8e0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e0e - {0.128906f, 0.154785f, 0.144531f, 0.170410f, -0.4375f, -29.3125f, 30.0000f, 32, 32}, // 8e0f + {0.177246f, 0.173828f, 0.192871f, 0.189453f, -0.4375f, -29.3125f, 30.0000f, 32, 32}, // 8e0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e12 @@ -17647,7 +17948,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e8b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e8c - {0.752441f, 0.319824f, 0.768066f, 0.334961f, -1.0000f, -28.4375f, 30.0000f, 32, 31}, // 8e8d + {0.352539f, 0.341797f, 0.368164f, 0.356934f, -1.0000f, -28.4375f, 30.0000f, 32, 31}, // 8e8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8e90 @@ -17677,7 +17978,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ea8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ea9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8eaa - {0.000000f, 0.453125f, 0.014648f, 0.468750f, 0.1875f, -29.6250f, 30.0000f, 30, 32}, // 8eab + {0.219238f, 0.475098f, 0.233887f, 0.490723f, 0.1875f, -29.6250f, 30.0000f, 30, 32}, // 8eab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8eac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ead {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8eae @@ -17708,15 +18009,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ec7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ec8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ec9 - {0.784668f, 0.319824f, 0.799805f, 0.335449f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 8eca + {0.624023f, 0.341797f, 0.639160f, 0.357422f, -0.1250f, -29.0000f, 30.0000f, 31, 32}, // 8eca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ecb - {0.145020f, 0.154785f, 0.160645f, 0.170410f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 8ecc - {0.924805f, 0.647461f, 0.938965f, 0.662109f, 0.6875f, -27.5625f, 30.0000f, 29, 30}, // 8ecd + {0.193359f, 0.173828f, 0.208984f, 0.189453f, -0.4375f, -29.0000f, 30.0000f, 32, 32}, // 8ecc + {0.558105f, 0.677246f, 0.572266f, 0.691895f, 0.6875f, -27.5625f, 30.0000f, 29, 30}, // 8ecd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ece {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ecf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ed0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ed1 - {0.300293f, 0.402832f, 0.315430f, 0.417969f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 8ed2 + {0.109375f, 0.425781f, 0.124512f, 0.440918f, -0.3750f, -28.9375f, 30.0000f, 31, 31}, // 8ed2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ed3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ed4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ed5 @@ -17729,10 +18030,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8edc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8edd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ede - {0.322266f, 0.155273f, 0.337891f, 0.170898f, -0.1250f, -29.2500f, 30.0000f, 32, 32}, // 8edf + {0.161133f, 0.174316f, 0.176758f, 0.189941f, -0.1250f, -29.2500f, 30.0000f, 32, 32}, // 8edf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ee0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ee1 - {0.832520f, 0.319824f, 0.848145f, 0.334961f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8ee2 + {0.368652f, 0.342773f, 0.384277f, 0.357910f, -0.4375f, -28.8750f, 30.0000f, 32, 31}, // 8ee2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ee3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ee4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ee5 @@ -17754,24 +18055,24 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ef5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ef6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ef7 - {0.047363f, 0.455078f, 0.062012f, 0.470703f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 8ef8 + {0.709961f, 0.475098f, 0.724609f, 0.490723f, -0.2500f, -28.9375f, 30.0000f, 30, 32}, // 8ef8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ef9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8efa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8efb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8efc - {0.941406f, 0.319824f, 0.957031f, 0.334961f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 8efd + {0.706055f, 0.342773f, 0.721680f, 0.357910f, -0.5000f, -29.0000f, 30.0000f, 32, 31}, // 8efd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8efe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8eff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f02 - {0.975098f, 0.319824f, 0.990723f, 0.334961f, -0.2500f, -28.8750f, 30.0000f, 32, 31}, // 8f03 + {0.655762f, 0.343262f, 0.671387f, 0.358398f, -0.2500f, -28.8750f, 30.0000f, 32, 31}, // 8f03 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f08 - {0.364258f, 0.405273f, 0.379395f, 0.420410f, -0.1250f, -29.1250f, 30.0000f, 31, 31}, // 8f09 + {0.157715f, 0.426270f, 0.172852f, 0.441406f, -0.1250f, -29.1250f, 30.0000f, 31, 31}, // 8f09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f0c @@ -17791,7 +18092,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f1b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f1c - {0.272461f, 0.320313f, 0.288086f, 0.335449f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 8f1d + {0.318359f, 0.343750f, 0.333984f, 0.358887f, -0.8125f, -29.0000f, 30.0000f, 32, 31}, // 8f1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f1f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f20 @@ -17803,8 +18104,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f28 - {0.497559f, 0.320313f, 0.512695f, 0.335938f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 8f29 - {0.201660f, 0.031250f, 0.217285f, 0.047363f, -0.5000f, -30.0625f, 30.0000f, 32, 33}, // 8f2a + {0.785645f, 0.343750f, 0.800781f, 0.359375f, -0.3750f, -29.1875f, 30.0000f, 31, 32}, // 8f29 + {0.292480f, 0.047363f, 0.308105f, 0.063477f, -0.5000f, -30.0625f, 30.0000f, 32, 33}, // 8f2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f2d @@ -17818,7 +18119,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f37 - {0.338379f, 0.155273f, 0.354004f, 0.170898f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 8f38 + {0.000000f, 0.175293f, 0.015625f, 0.190918f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 8f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f3b @@ -17830,12 +18131,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f43 - {0.379883f, 0.405762f, 0.395020f, 0.420898f, -0.4375f, -29.1250f, 30.0000f, 31, 31}, // 8f44 + {0.000000f, 0.426758f, 0.015137f, 0.441895f, -0.4375f, -29.1250f, 30.0000f, 31, 31}, // 8f44 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f48 - {0.109375f, 0.406250f, 0.124512f, 0.421387f, -0.3750f, -28.8750f, 30.0000f, 31, 31}, // 8f49 + {0.015625f, 0.426758f, 0.030762f, 0.441895f, -0.3750f, -28.8750f, 30.0000f, 31, 31}, // 8f49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f4b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f4c @@ -17870,10 +18171,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f6b - {0.000000f, 0.407227f, 0.015137f, 0.422363f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 8f6c + {0.125000f, 0.426758f, 0.140137f, 0.441895f, -0.4375f, -28.8125f, 30.0000f, 31, 31}, // 8f6c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f6e - {0.623535f, 0.320313f, 0.638672f, 0.335938f, 0.1875f, -29.1875f, 30.0000f, 31, 32}, // 8f6f + {0.493164f, 0.344727f, 0.508301f, 0.360352f, 0.1875f, -29.1875f, 30.0000f, 31, 32}, // 8f6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f72 @@ -17887,13 +18188,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f7a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f7b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f7c - {0.015625f, 0.408691f, 0.030762f, 0.423828f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 8f7d + {0.731934f, 0.427734f, 0.747070f, 0.442871f, -0.3125f, -28.7500f, 30.0000f, 31, 31}, // 8f7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f82 - {0.705078f, 0.320313f, 0.720215f, 0.335938f, -0.3750f, -29.0625f, 30.0000f, 31, 32}, // 8f83 + {0.688477f, 0.344727f, 0.703613f, 0.360352f, -0.3750f, -29.0625f, 30.0000f, 31, 32}, // 8f83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f86 @@ -17917,10 +18218,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f9a - {0.608887f, 0.538086f, 0.623535f, 0.553223f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 8f9b + {0.755371f, 0.562500f, 0.770020f, 0.577637f, 0.3125f, -28.8750f, 30.0000f, 30, 31}, // 8f9b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f9c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f9d - {0.768555f, 0.320313f, 0.784180f, 0.335449f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 8f9e + {0.207031f, 0.345215f, 0.222656f, 0.360352f, -0.4375f, -29.0000f, 30.0000f, 32, 31}, // 8f9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8f9f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa1 @@ -17930,7 +18231,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa7 - {0.000000f, 0.156250f, 0.015625f, 0.171875f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 8fa8 + {0.016113f, 0.175293f, 0.031738f, 0.190918f, -0.8750f, -28.9375f, 30.0000f, 32, 32}, // 8fa8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fa9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8faa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fab @@ -17939,18 +18240,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8faf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb0 - {0.015137f, 0.456055f, 0.030762f, 0.470703f, -1.0000f, -27.6875f, 30.0000f, 32, 30}, // 8fb1 - {0.016113f, 0.156250f, 0.031738f, 0.171875f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 8fb2 + {0.234375f, 0.475586f, 0.250000f, 0.490234f, -1.0000f, -27.6875f, 30.0000f, 32, 30}, // 8fb1 + {0.032227f, 0.175293f, 0.047852f, 0.190918f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 8fb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fb8 - {0.281250f, 0.457031f, 0.296875f, 0.471680f, -1.0000f, -28.6875f, 30.0000f, 32, 30}, // 8fb9 - {0.433594f, 0.556152f, 0.449219f, 0.570313f, -1.0000f, -28.1250f, 30.0000f, 32, 29}, // 8fba + {0.725098f, 0.475586f, 0.740723f, 0.490234f, -1.0000f, -28.6875f, 30.0000f, 32, 30}, // 8fb9 + {0.214355f, 0.585449f, 0.229980f, 0.599609f, -1.0000f, -28.1250f, 30.0000f, 32, 29}, // 8fba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fbb - {0.816895f, 0.320313f, 0.832520f, 0.335449f, -1.0000f, -28.6250f, 30.0000f, 32, 31}, // 8fbc + {0.508789f, 0.345215f, 0.524414f, 0.360352f, -1.0000f, -28.6250f, 30.0000f, 32, 31}, // 8fbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fbf @@ -17959,33 +18260,33 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc4 - {0.893555f, 0.320313f, 0.909180f, 0.335449f, -0.8750f, -28.5000f, 30.0000f, 32, 31}, // 8fc5 + {0.639648f, 0.345215f, 0.655273f, 0.360352f, -0.8750f, -28.5000f, 30.0000f, 32, 31}, // 8fc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc6 - {0.046875f, 0.409180f, 0.062012f, 0.424316f, -0.9375f, -28.8125f, 30.0000f, 31, 31}, // 8fc7 + {0.220703f, 0.428223f, 0.235840f, 0.443359f, -0.9375f, -28.8125f, 30.0000f, 31, 31}, // 8fc7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fc9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fcb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fcc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fcd - {0.925293f, 0.320313f, 0.940918f, 0.335449f, -1.1250f, -29.0000f, 30.0000f, 32, 31}, // 8fce + {0.189941f, 0.345703f, 0.205566f, 0.360840f, -1.1250f, -29.0000f, 30.0000f, 32, 31}, // 8fce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fcf - {0.828125f, 0.457031f, 0.843750f, 0.471680f, -1.0625f, -28.0000f, 30.0000f, 32, 30}, // 8fd0 - {0.957520f, 0.320313f, 0.973145f, 0.335449f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 8fd1 + {0.016113f, 0.476074f, 0.031738f, 0.490723f, -1.0625f, -28.0000f, 30.0000f, 32, 30}, // 8fd0 + {0.541016f, 0.345703f, 0.556641f, 0.360840f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 8fd1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd3 - {0.240234f, 0.320801f, 0.255859f, 0.335938f, -0.7500f, -28.6875f, 30.0000f, 32, 31}, // 8fd4 + {0.557129f, 0.345703f, 0.572754f, 0.360840f, -0.7500f, -28.6875f, 30.0000f, 32, 31}, // 8fd4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fd8 - {0.062500f, 0.457520f, 0.078125f, 0.472168f, -0.9375f, -28.4375f, 30.0000f, 32, 30}, // 8fd9 + {0.423340f, 0.476074f, 0.438965f, 0.490723f, -0.9375f, -28.4375f, 30.0000f, 32, 30}, // 8fd9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fda - {0.031250f, 0.458008f, 0.046875f, 0.472656f, -1.3125f, -28.5625f, 30.0000f, 32, 30}, // 8fdb + {0.741211f, 0.476074f, 0.756836f, 0.490723f, -1.3125f, -28.5625f, 30.0000f, 32, 30}, // 8fdb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fdc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fdd - {0.155762f, 0.458008f, 0.171387f, 0.472656f, -1.0000f, -28.3125f, 30.0000f, 32, 30}, // 8fde - {0.901855f, 0.538086f, 0.916992f, 0.552734f, -0.8125f, -28.2500f, 30.0000f, 31, 30}, // 8fdf + {0.439453f, 0.477051f, 0.455078f, 0.491699f, -1.0000f, -28.3125f, 30.0000f, 32, 30}, // 8fde + {0.291992f, 0.562988f, 0.307129f, 0.577637f, -0.8125f, -28.2500f, 30.0000f, 31, 30}, // 8fdf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fe0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fe1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fe2 @@ -17997,63 +18298,63 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fe8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fe9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fea - {0.364746f, 0.320801f, 0.380371f, 0.335938f, -0.8125f, -29.0625f, 30.0000f, 32, 31}, // 8feb + {0.671875f, 0.345703f, 0.687500f, 0.360840f, -0.8125f, -29.0625f, 30.0000f, 32, 31}, // 8feb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fec - {0.449707f, 0.320801f, 0.465332f, 0.335938f, -1.1250f, -28.5625f, 30.0000f, 32, 31}, // 8fed + {0.047852f, 0.346191f, 0.063477f, 0.361328f, -1.1250f, -28.5625f, 30.0000f, 32, 31}, // 8fed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fef - {0.656250f, 0.320801f, 0.671875f, 0.335938f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 8ff0 + {0.573242f, 0.346191f, 0.588867f, 0.361328f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 8ff0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff6 - {0.909668f, 0.320801f, 0.925293f, 0.335938f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 8ff7 + {0.079590f, 0.346680f, 0.095215f, 0.361816f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 8ff7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ff9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ffa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ffb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ffc - {0.191406f, 0.321289f, 0.207031f, 0.336426f, -1.1250f, -29.3125f, 30.0000f, 32, 31}, // 8ffd + {0.143066f, 0.346680f, 0.158691f, 0.361816f, -1.1250f, -29.3125f, 30.0000f, 32, 31}, // 8ffd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8ffe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 8fff - {0.256348f, 0.321289f, 0.271973f, 0.336426f, -1.1250f, -28.5625f, 30.0000f, 32, 31}, // 9000 - {0.032227f, 0.156250f, 0.047852f, 0.171875f, -1.1250f, -29.8125f, 30.0000f, 32, 32}, // 9001 - {0.223633f, 0.321777f, 0.238770f, 0.337402f, -0.7500f, -29.8125f, 30.0000f, 31, 32}, // 9002 - {0.207520f, 0.322266f, 0.223145f, 0.337402f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 9003 + {0.589355f, 0.346680f, 0.604980f, 0.361816f, -1.1250f, -28.5625f, 30.0000f, 32, 31}, // 9000 + {0.762207f, 0.175781f, 0.777832f, 0.191406f, -1.1250f, -29.8125f, 30.0000f, 32, 32}, // 9001 + {0.770508f, 0.344727f, 0.785645f, 0.360352f, -0.7500f, -29.8125f, 30.0000f, 31, 32}, // 9002 + {0.605469f, 0.347168f, 0.621094f, 0.362305f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 9003 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9004 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9005 - {0.413574f, 0.322266f, 0.429199f, 0.337402f, -1.1250f, -29.1875f, 30.0000f, 32, 31}, // 9006 + {0.063965f, 0.347656f, 0.079590f, 0.362793f, -1.1250f, -29.1875f, 30.0000f, 32, 31}, // 9006 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9007 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9008 - {0.538574f, 0.458008f, 0.554199f, 0.472656f, -1.1875f, -28.2500f, 30.0000f, 32, 30}, // 9009 + {0.502441f, 0.478027f, 0.518066f, 0.492676f, -1.1875f, -28.2500f, 30.0000f, 32, 30}, // 9009 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 900a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 900b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 900c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 900d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 900e - {0.465820f, 0.322266f, 0.481445f, 0.337402f, -1.0625f, -29.0000f, 30.0000f, 32, 31}, // 900f - {0.481934f, 0.322266f, 0.497559f, 0.337402f, -1.3750f, -28.5000f, 30.0000f, 32, 31}, // 9010 + {0.111328f, 0.347656f, 0.126953f, 0.362793f, -1.0625f, -29.0000f, 30.0000f, 32, 31}, // 900f + {0.159180f, 0.348145f, 0.174805f, 0.363281f, -1.3750f, -28.5000f, 30.0000f, 32, 31}, // 9010 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9011 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9012 - {0.319336f, 0.324707f, 0.334961f, 0.339844f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9013 - {0.048340f, 0.157715f, 0.063965f, 0.173340f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 9014 + {0.000000f, 0.348633f, 0.015625f, 0.363770f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9013 + {0.778320f, 0.175781f, 0.793945f, 0.191406f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 9014 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9015 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9016 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9017 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9018 - {0.680176f, 0.458496f, 0.695801f, 0.473145f, -0.6875f, -28.5000f, 30.0000f, 32, 30}, // 9019 - {0.380859f, 0.327148f, 0.396484f, 0.342285f, -1.1250f, -28.5000f, 30.0000f, 32, 31}, // 901a + {0.809570f, 0.478027f, 0.825195f, 0.492676f, -0.6875f, -28.5000f, 30.0000f, 32, 30}, // 9019 + {0.016113f, 0.348633f, 0.031738f, 0.363770f, -1.1250f, -28.5000f, 30.0000f, 32, 31}, // 901a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 901b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 901c - {0.396973f, 0.327637f, 0.412598f, 0.342773f, -1.3125f, -28.8750f, 30.0000f, 32, 31}, // 901d + {0.127441f, 0.348633f, 0.143066f, 0.363770f, -1.3125f, -28.8750f, 30.0000f, 32, 31}, // 901d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 901e - {0.110840f, 0.328125f, 0.126465f, 0.343262f, -1.1250f, -29.0625f, 30.0000f, 32, 31}, // 901f - {0.000000f, 0.328613f, 0.015625f, 0.343750f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 9020 + {0.738281f, 0.349121f, 0.753906f, 0.364258f, -1.1250f, -29.0625f, 30.0000f, 32, 31}, // 901f + {0.223145f, 0.350098f, 0.238770f, 0.365234f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 9020 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9021 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9022 - {0.016113f, 0.330566f, 0.031738f, 0.345703f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9023 + {0.270020f, 0.350098f, 0.285645f, 0.365234f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9023 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9024 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9025 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9026 @@ -18064,17 +18365,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 902b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 902c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 902d - {0.062988f, 0.331055f, 0.078613f, 0.346191f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 902e + {0.286133f, 0.350098f, 0.301758f, 0.365234f, -1.1250f, -28.8750f, 30.0000f, 32, 31}, // 902e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 902f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9030 - {0.715332f, 0.458496f, 0.730957f, 0.473145f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 9031 - {0.079102f, 0.331055f, 0.094727f, 0.346191f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9032 + {0.842773f, 0.478027f, 0.858398f, 0.492676f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 9031 + {0.722168f, 0.350098f, 0.737793f, 0.365234f, -0.9375f, -28.9375f, 30.0000f, 32, 31}, // 9032 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9033 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9034 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9035 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9036 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9037 - {0.032227f, 0.332031f, 0.047852f, 0.347168f, -0.9375f, -29.2500f, 30.0000f, 32, 31}, // 9038 + {0.239258f, 0.351563f, 0.254883f, 0.366699f, -0.9375f, -29.2500f, 30.0000f, 32, 31}, // 9038 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9039 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 903a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 903b @@ -18084,26 +18385,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 903f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9040 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9041 - {0.064453f, 0.157715f, 0.080078f, 0.173340f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 9042 + {0.273926f, 0.176270f, 0.289551f, 0.191895f, -1.1250f, -29.5000f, 30.0000f, 32, 32}, // 9042 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9043 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9044 - {0.171875f, 0.458984f, 0.187500f, 0.473633f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9045 + {0.923828f, 0.478516f, 0.939453f, 0.493164f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9045 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9046 - {0.554688f, 0.459473f, 0.570313f, 0.474121f, -0.9375f, -28.4375f, 30.0000f, 32, 30}, // 9047 + {0.939941f, 0.478516f, 0.955566f, 0.493164f, -0.9375f, -28.4375f, 30.0000f, 32, 30}, // 9047 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9048 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9049 - {0.080566f, 0.157715f, 0.096191f, 0.173340f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // 904a - {0.570801f, 0.459473f, 0.586426f, 0.474121f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 904b + {0.290039f, 0.176270f, 0.305664f, 0.191895f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // 904a + {0.972168f, 0.478516f, 0.987793f, 0.493164f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 904b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 904c - {0.763672f, 0.459473f, 0.779297f, 0.474121f, -1.0625f, -28.4375f, 30.0000f, 32, 30}, // 904d - {0.489258f, 0.459961f, 0.504883f, 0.474609f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 904e + {0.284180f, 0.479492f, 0.299805f, 0.494141f, -1.0625f, -28.4375f, 30.0000f, 32, 30}, // 904d + {0.956055f, 0.479492f, 0.971680f, 0.494141f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 904e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 904f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9050 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9051 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9052 - {0.096680f, 0.157715f, 0.112305f, 0.173340f, -1.1250f, -29.4375f, 30.0000f, 32, 32}, // 9053 - {0.288574f, 0.333008f, 0.304199f, 0.348145f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 9054 - {0.112793f, 0.159668f, 0.128418f, 0.175293f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 9055 + {0.306152f, 0.176270f, 0.321777f, 0.191895f, -1.1250f, -29.4375f, 30.0000f, 32, 32}, // 9053 + {0.032227f, 0.352051f, 0.047852f, 0.367188f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 9054 + {0.322266f, 0.176270f, 0.337891f, 0.191895f, -0.9375f, -29.3750f, 30.0000f, 32, 32}, // 9055 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9056 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9057 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9058 @@ -18114,43 +18415,43 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 905d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 905e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 905f - {0.158691f, 0.333984f, 0.174316f, 0.349121f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 9060 + {0.443848f, 0.352051f, 0.459473f, 0.367188f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 9060 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9061 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9062 - {0.174805f, 0.333984f, 0.190430f, 0.349121f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 9063 + {0.459961f, 0.352051f, 0.475586f, 0.367188f, -1.3125f, -29.0000f, 30.0000f, 32, 31}, // 9063 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9064 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9065 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9066 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9067 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9068 - {0.560547f, 0.333984f, 0.576172f, 0.349121f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 9069 + {0.754395f, 0.352051f, 0.770020f, 0.367188f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 9069 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 906a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 906b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 906c - {0.095215f, 0.334473f, 0.110840f, 0.349609f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 906d - {0.335449f, 0.334473f, 0.351074f, 0.349609f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 906e + {0.476074f, 0.352539f, 0.491699f, 0.367676f, -1.1250f, -28.9375f, 30.0000f, 32, 31}, // 906d + {0.302246f, 0.353027f, 0.317871f, 0.368164f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 906e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 906f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9070 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9071 - {0.591797f, 0.334473f, 0.607422f, 0.349609f, -0.6250f, -28.5000f, 30.0000f, 32, 31}, // 9072 + {0.820801f, 0.353027f, 0.836426f, 0.368164f, -0.6250f, -28.5000f, 30.0000f, 32, 31}, // 9072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9073 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9074 - {0.639160f, 0.334473f, 0.654785f, 0.349609f, -1.0000f, -29.2500f, 30.0000f, 32, 31}, // 9075 + {0.852539f, 0.353516f, 0.868164f, 0.368652f, -1.0000f, -29.2500f, 30.0000f, 32, 31}, // 9075 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9076 - {0.586914f, 0.459961f, 0.602539f, 0.474609f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9077 - {0.663574f, 0.459961f, 0.679199f, 0.474609f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 9078 + {0.907715f, 0.479980f, 0.923340f, 0.494629f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9077 + {0.858887f, 0.480469f, 0.874512f, 0.495117f, -0.9375f, -28.0000f, 30.0000f, 32, 30}, // 9078 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9079 - {0.800293f, 0.334473f, 0.815918f, 0.349609f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 907a + {0.524902f, 0.354004f, 0.540527f, 0.369141f, -0.9375f, -29.0625f, 30.0000f, 32, 31}, // 907a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 907b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 907c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 907d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 907e - {0.877930f, 0.334473f, 0.893555f, 0.349609f, -1.1250f, -28.7500f, 30.0000f, 32, 31}, // 907f + {0.384766f, 0.354492f, 0.400391f, 0.369629f, -1.1250f, -28.7500f, 30.0000f, 32, 31}, // 907f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9080 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9081 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9082 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9083 - {0.812012f, 0.459961f, 0.827637f, 0.474609f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9084 + {0.393555f, 0.480957f, 0.409180f, 0.495605f, -0.9375f, -28.2500f, 30.0000f, 32, 30}, // 9084 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9085 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9086 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9087 @@ -18184,11 +18485,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a5 - {0.844238f, 0.458984f, 0.858887f, 0.474609f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 90a6 + {0.455566f, 0.478516f, 0.470215f, 0.494141f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 90a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90a9 - {0.387695f, 0.538574f, 0.402832f, 0.553223f, -0.6250f, -27.5625f, 30.0000f, 31, 30}, // 90aa + {0.653809f, 0.563965f, 0.668945f, 0.578613f, -0.6250f, -27.5625f, 30.0000f, 31, 30}, // 90aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ad @@ -18202,10 +18503,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90b7 - {0.062500f, 0.409668f, 0.077637f, 0.424805f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 90b8 + {0.253418f, 0.428223f, 0.268555f, 0.443359f, -0.1250f, -28.8750f, 30.0000f, 31, 31}, // 90b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ba - {0.031250f, 0.410156f, 0.046387f, 0.425293f, -0.7500f, -28.8750f, 30.0000f, 31, 31}, // 90bb + {0.715332f, 0.428223f, 0.730469f, 0.443359f, -0.7500f, -28.8750f, 30.0000f, 31, 31}, // 90bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90be @@ -18220,11 +18521,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90c9 - {0.283691f, 0.411133f, 0.298828f, 0.426270f, -0.4375f, -28.6875f, 30.0000f, 31, 31}, // 90ca + {0.269043f, 0.428711f, 0.284180f, 0.443848f, -0.4375f, -28.6875f, 30.0000f, 31, 31}, // 90ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90cd - {0.828613f, 0.411133f, 0.843750f, 0.426270f, -0.5000f, -29.0000f, 30.0000f, 31, 31}, // 90ce + {0.236328f, 0.429688f, 0.251465f, 0.444824f, -0.5000f, -29.0000f, 30.0000f, 31, 31}, // 90ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90d1 @@ -18243,19 +18544,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e0 - {0.920410f, 0.459961f, 0.936035f, 0.474609f, -0.8125f, -27.6250f, 30.0000f, 32, 30}, // 90e1 + {0.825684f, 0.480957f, 0.841309f, 0.495605f, -0.8125f, -27.6250f, 30.0000f, 32, 30}, // 90e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e7 - {0.844238f, 0.411133f, 0.859375f, 0.426270f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 90e8 + {0.031250f, 0.430176f, 0.046387f, 0.445313f, -0.2500f, -28.9375f, 30.0000f, 31, 31}, // 90e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ec - {0.156250f, 0.412109f, 0.171387f, 0.427246f, -0.4375f, -29.1250f, 30.0000f, 31, 31}, // 90ed + {0.428223f, 0.430176f, 0.443359f, 0.445313f, -0.4375f, -29.1250f, 30.0000f, 31, 31}, // 90ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f0 @@ -18263,15 +18564,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f4 - {0.126953f, 0.334961f, 0.142090f, 0.350586f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 90f5 + {0.427246f, 0.354492f, 0.442383f, 0.370117f, -0.4375f, -29.0000f, 30.0000f, 31, 32}, // 90f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f6 - {0.161133f, 0.160156f, 0.176758f, 0.175781f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 90f7 + {0.338379f, 0.176270f, 0.354004f, 0.191895f, -0.8750f, -29.0625f, 30.0000f, 32, 32}, // 90f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90fc - {0.513184f, 0.334961f, 0.528320f, 0.350586f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 90fd + {0.930176f, 0.354492f, 0.945313f, 0.370117f, -0.5000f, -29.1250f, 30.0000f, 31, 32}, // 90fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 90ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9100 @@ -18350,15 +18651,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9149 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 914a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 914b - {0.078613f, 0.460449f, 0.093262f, 0.476074f, -0.0625f, -29.3750f, 30.0000f, 30, 32}, // 914c - {0.656250f, 0.538574f, 0.671387f, 0.553223f, -0.1250f, -27.7500f, 30.0000f, 31, 30}, // 914d + {0.330566f, 0.480469f, 0.345215f, 0.496094f, -0.0625f, -29.3750f, 30.0000f, 30, 32}, // 914c + {0.045898f, 0.564453f, 0.061035f, 0.579102f, -0.1250f, -27.7500f, 30.0000f, 31, 30}, // 914d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 914e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 914f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9150 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9151 - {0.077148f, 0.539063f, 0.092285f, 0.553711f, -0.6250f, -27.7500f, 30.0000f, 31, 30}, // 9152 + {0.513672f, 0.564453f, 0.528809f, 0.579102f, -0.6250f, -27.7500f, 30.0000f, 31, 30}, // 9152 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9153 - {0.217773f, 0.031250f, 0.233887f, 0.046875f, -0.8125f, -29.1250f, 30.0000f, 33, 32}, // 9154 + {0.308594f, 0.047363f, 0.324707f, 0.062988f, -0.8125f, -29.1250f, 30.0000f, 33, 32}, // 9154 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9155 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9156 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9157 @@ -18372,7 +18673,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 915f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9160 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9161 - {0.528809f, 0.334961f, 0.544434f, 0.350098f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 9162 + {0.334473f, 0.354980f, 0.350098f, 0.370117f, -0.5625f, -29.0625f, 30.0000f, 32, 31}, // 9162 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9163 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9164 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9165 @@ -18380,9 +18681,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9167 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9168 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9169 - {0.193359f, 0.160156f, 0.208984f, 0.175781f, -0.5000f, -29.2500f, 30.0000f, 32, 32}, // 916a + {0.257813f, 0.176758f, 0.273438f, 0.192383f, -0.5000f, -29.2500f, 30.0000f, 32, 32}, // 916a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 916b - {0.187988f, 0.460449f, 0.202637f, 0.476074f, -0.0625f, -29.0625f, 30.0000f, 30, 32}, // 916c + {0.875000f, 0.480957f, 0.889648f, 0.496582f, -0.0625f, -29.0625f, 30.0000f, 30, 32}, // 916c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 916d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 916e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 916f @@ -18391,10 +18692,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9172 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9173 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9174 - {0.607910f, 0.334961f, 0.623047f, 0.350586f, -0.1875f, -28.9375f, 30.0000f, 31, 32}, // 9175 + {0.400879f, 0.354980f, 0.416016f, 0.370605f, -0.1875f, -28.9375f, 30.0000f, 31, 32}, // 9175 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9176 - {0.138184f, 0.539063f, 0.152832f, 0.554199f, -0.2500f, -28.8750f, 30.0000f, 30, 31}, // 9177 - {0.370605f, 0.160156f, 0.386230f, 0.175781f, -0.8125f, -29.5000f, 30.0000f, 32, 32}, // 9178 + {0.200195f, 0.564453f, 0.214844f, 0.579590f, -0.2500f, -28.8750f, 30.0000f, 30, 31}, // 9177 + {0.498535f, 0.177734f, 0.514160f, 0.193359f, -0.8125f, -29.5000f, 30.0000f, 32, 32}, // 9178 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9179 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 917a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 917b @@ -18430,7 +18731,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9199 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 919a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 919b - {0.386719f, 0.160156f, 0.402344f, 0.175781f, -0.2500f, -29.4375f, 30.0000f, 32, 32}, // 919c + {0.514648f, 0.177734f, 0.530273f, 0.193359f, -0.2500f, -29.4375f, 30.0000f, 32, 32}, // 919c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 919d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 919e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 919f @@ -18458,7 +18759,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91b7 - {0.669434f, 0.160156f, 0.685059f, 0.175781f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 91b8 + {0.794434f, 0.177734f, 0.810059f, 0.193359f, -0.5000f, -29.1250f, 30.0000f, 32, 32}, // 91b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91bb @@ -18474,16 +18775,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91c7 - {0.801270f, 0.177246f, 0.817383f, 0.192383f, -0.7500f, -28.8125f, 30.0000f, 33, 31}, // 91c8 + {0.096680f, 0.198730f, 0.112793f, 0.213867f, -0.7500f, -28.8125f, 30.0000f, 33, 31}, // 91c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91cb - {0.709473f, 0.616699f, 0.724609f, 0.630859f, -0.5000f, -27.8750f, 30.0000f, 31, 29}, // 91cc - {0.214355f, 0.539063f, 0.229492f, 0.553711f, 0.0625f, -28.9375f, 30.0000f, 31, 30}, // 91cd - {0.308594f, 0.539063f, 0.323730f, 0.553711f, -0.1250f, -27.5625f, 30.0000f, 31, 30}, // 91ce - {0.119141f, 0.617188f, 0.134277f, 0.631348f, -0.3750f, -27.6875f, 30.0000f, 31, 29}, // 91cf + {0.936035f, 0.645508f, 0.951172f, 0.659668f, -0.5000f, -27.8750f, 30.0000f, 31, 29}, // 91cc + {0.561035f, 0.564453f, 0.576172f, 0.579102f, 0.0625f, -28.9375f, 30.0000f, 31, 30}, // 91cd + {0.638672f, 0.564453f, 0.653809f, 0.579102f, -0.1250f, -27.5625f, 30.0000f, 31, 30}, // 91ce + {0.951660f, 0.645508f, 0.966797f, 0.659668f, -0.3750f, -27.6875f, 30.0000f, 31, 29}, // 91cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91d0 - {0.720703f, 0.334961f, 0.736328f, 0.350098f, -0.4375f, -29.6875f, 30.0000f, 32, 31}, // 91d1 + {0.885254f, 0.354980f, 0.900879f, 0.370117f, -0.4375f, -29.6875f, 30.0000f, 32, 31}, // 91d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91d4 @@ -18495,13 +18796,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91dc - {0.848633f, 0.334961f, 0.864258f, 0.350098f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 91dd + {0.801270f, 0.355957f, 0.816895f, 0.371094f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 91dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e2 - {0.429688f, 0.335449f, 0.444824f, 0.351074f, -0.3750f, -29.2500f, 30.0000f, 31, 32}, // 91e3 + {0.836914f, 0.355957f, 0.852051f, 0.371582f, -0.3750f, -29.2500f, 30.0000f, 31, 32}, // 91e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 91e6 @@ -18543,7 +18844,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 920a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 920b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 920c - {0.544922f, 0.335449f, 0.560547f, 0.350586f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 920d + {0.868652f, 0.355957f, 0.884277f, 0.371094f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 920d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 920e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 920f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9210 @@ -18551,7 +18852,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9212 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9213 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9214 - {0.313477f, 0.460449f, 0.329102f, 0.475098f, -0.8125f, -29.0625f, 30.0000f, 32, 30}, // 9215 + {0.375977f, 0.481445f, 0.391602f, 0.496094f, -0.8125f, -29.0625f, 30.0000f, 32, 30}, // 9215 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9216 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9217 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9218 @@ -18582,7 +18883,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9231 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9232 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9233 - {0.409668f, 0.031250f, 0.425781f, 0.046875f, -1.0000f, -29.3750f, 30.0000f, 33, 32}, // 9234 + {0.325195f, 0.047363f, 0.341309f, 0.062988f, -1.0000f, -29.3750f, 30.0000f, 33, 32}, // 9234 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9235 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9236 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9237 @@ -18598,7 +18899,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9241 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9242 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9243 - {0.426270f, 0.031250f, 0.442383f, 0.046875f, -1.2500f, -29.2500f, 30.0000f, 33, 32}, // 9244 + {0.341797f, 0.047363f, 0.357910f, 0.062988f, -1.2500f, -29.2500f, 30.0000f, 33, 32}, // 9244 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9245 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9246 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9247 @@ -18621,14 +18922,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9258 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9259 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 925a - {0.672363f, 0.335449f, 0.687988f, 0.350586f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 925b + {0.945801f, 0.355957f, 0.961426f, 0.371094f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 925b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 925c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 925d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 925e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 925f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9260 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9261 - {0.616699f, 0.032227f, 0.632813f, 0.047852f, -1.1250f, -28.9375f, 30.0000f, 33, 32}, // 9262 + {0.358398f, 0.047363f, 0.374512f, 0.062988f, -1.1250f, -28.9375f, 30.0000f, 33, 32}, // 9262 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9263 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9264 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9265 @@ -18643,7 +18944,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 926e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 926f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9270 - {0.688477f, 0.335449f, 0.704102f, 0.350586f, -0.9375f, -28.7500f, 30.0000f, 32, 31}, // 9271 + {0.961914f, 0.355957f, 0.977539f, 0.371094f, -0.9375f, -28.7500f, 30.0000f, 32, 31}, // 9271 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9273 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9274 @@ -18658,12 +18959,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 927d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 927e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 927f - {0.736816f, 0.335449f, 0.752441f, 0.350586f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 9280 + {0.978027f, 0.355957f, 0.993652f, 0.371094f, -0.7500f, -28.8750f, 30.0000f, 32, 31}, // 9280 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9281 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9282 - {0.177246f, 0.160645f, 0.192871f, 0.176270f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 9283 + {0.875977f, 0.179199f, 0.891602f, 0.194824f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 9283 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9284 - {0.171875f, 0.412109f, 0.187012f, 0.427246f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 9285 + {0.443848f, 0.430176f, 0.458984f, 0.445313f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 9285 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9286 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9287 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9288 @@ -18675,14 +18976,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 928e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 928f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9290 - {0.556152f, 0.161133f, 0.571777f, 0.176758f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 9291 + {0.370605f, 0.180664f, 0.386230f, 0.196289f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 9291 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9292 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9293 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9294 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9295 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9296 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9297 - {0.408203f, 0.460449f, 0.422852f, 0.476074f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // 9298 + {0.890137f, 0.481445f, 0.904785f, 0.497070f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // 9298 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9299 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 929a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 929b @@ -18703,7 +19004,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ac - {0.554199f, 0.412109f, 0.569336f, 0.427246f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 92ad + {0.747559f, 0.430176f, 0.762695f, 0.445313f, -0.3750f, -28.8125f, 30.0000f, 31, 31}, // 92ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b0 @@ -18713,7 +19014,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b6 - {0.576660f, 0.335449f, 0.591797f, 0.351074f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 92b7 + {0.901367f, 0.356445f, 0.916504f, 0.372070f, -0.5000f, -29.0000f, 30.0000f, 31, 32}, // 92b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ba @@ -18767,13 +19068,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ec - {0.572266f, 0.161133f, 0.587891f, 0.176758f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 92ed + {0.418945f, 0.180664f, 0.434570f, 0.196289f, -0.8125f, -29.0625f, 30.0000f, 32, 32}, // 92ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f2 - {0.752930f, 0.335449f, 0.768555f, 0.350586f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 92f3 + {0.095703f, 0.356934f, 0.111328f, 0.372070f, -0.9375f, -29.1250f, 30.0000f, 32, 31}, // 92f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f6 @@ -18782,7 +19083,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92fb - {0.184570f, 0.539063f, 0.199219f, 0.554199f, -0.1875f, -28.7500f, 30.0000f, 30, 31}, // 92fc + {0.030273f, 0.564941f, 0.044922f, 0.580078f, -0.1875f, -28.7500f, 30.0000f, 30, 31}, // 92fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 92ff @@ -18790,7 +19091,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9301 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9302 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9303 - {0.588379f, 0.161133f, 0.604004f, 0.176758f, -0.3125f, -29.2500f, 30.0000f, 32, 32}, // 9304 + {0.435059f, 0.180664f, 0.450684f, 0.196289f, -0.3125f, -29.2500f, 30.0000f, 32, 32}, // 9304 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9305 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9306 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9307 @@ -18810,7 +19111,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9315 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9316 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9317 - {0.423340f, 0.460449f, 0.438965f, 0.475098f, -0.7500f, -29.0000f, 30.0000f, 32, 30}, // 9318 + {0.682617f, 0.481934f, 0.698242f, 0.496582f, -0.7500f, -29.0000f, 30.0000f, 32, 30}, // 9318 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9319 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 931a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 931b @@ -18818,7 +19119,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 931d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 931e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 931f - {0.604492f, 0.161133f, 0.620117f, 0.176758f, -0.7500f, -29.1875f, 30.0000f, 32, 32}, // 9320 + {0.451172f, 0.180664f, 0.466797f, 0.196289f, -0.7500f, -29.1875f, 30.0000f, 32, 32}, // 9320 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9321 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9322 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9323 @@ -18830,13 +19131,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9329 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 932a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 932b - {0.833008f, 0.335449f, 0.848633f, 0.350586f, -0.3125f, -29.0625f, 30.0000f, 32, 31}, // 932c + {0.350586f, 0.357422f, 0.366211f, 0.372559f, -0.3125f, -29.0625f, 30.0000f, 32, 31}, // 932c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 932d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 932e - {0.620605f, 0.161133f, 0.636230f, 0.176758f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 932f + {0.467285f, 0.180664f, 0.482910f, 0.196289f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 932f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9330 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9331 - {0.633301f, 0.032227f, 0.649414f, 0.047852f, -0.8750f, -29.1250f, 30.0000f, 33, 32}, // 9332 + {0.375000f, 0.047363f, 0.391113f, 0.062988f, -0.8750f, -29.1250f, 30.0000f, 33, 32}, // 9332 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9333 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9334 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9335 @@ -18877,7 +19178,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9358 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9359 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 935a - {0.941406f, 0.335449f, 0.957031f, 0.350586f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 935b + {0.621582f, 0.357910f, 0.637207f, 0.373047f, -0.7500f, -28.9375f, 30.0000f, 32, 31}, // 935b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 935c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 935d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 935e @@ -18903,7 +19204,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9372 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9373 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9374 - {0.973633f, 0.335449f, 0.989258f, 0.350586f, -0.8750f, -28.6875f, 30.0000f, 32, 31}, // 9375 + {0.366699f, 0.358398f, 0.382324f, 0.373535f, -0.8750f, -28.6875f, 30.0000f, 32, 31}, // 9375 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9376 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9377 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9378 @@ -18936,7 +19237,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9393 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9394 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9395 - {0.636719f, 0.161133f, 0.652344f, 0.176758f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 9396 + {0.570313f, 0.180664f, 0.585938f, 0.196289f, -0.8125f, -29.1250f, 30.0000f, 32, 32}, // 9396 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9397 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9398 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9399 @@ -18960,7 +19261,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93ad - {0.712402f, 0.161133f, 0.728027f, 0.176758f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 93ae + {0.915039f, 0.180664f, 0.930664f, 0.196289f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 93ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93b1 @@ -19011,7 +19312,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93e0 - {0.728516f, 0.161133f, 0.744141f, 0.176758f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 93e1 + {0.931152f, 0.180664f, 0.946777f, 0.196289f, -1.0000f, -29.1250f, 30.0000f, 32, 32}, // 93e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 93e4 @@ -19066,7 +19367,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9415 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9416 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9417 - {0.142578f, 0.335938f, 0.158203f, 0.351074f, -0.8125f, -29.1875f, 30.0000f, 32, 31}, // 9418 + {0.704102f, 0.358398f, 0.719727f, 0.373535f, -0.8125f, -29.1875f, 30.0000f, 32, 31}, // 9418 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9419 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 941a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 941b @@ -19123,7 +19424,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 944e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 944f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9450 - {0.619141f, 0.460449f, 0.634766f, 0.475098f, -1.1250f, -29.3750f, 30.0000f, 32, 30}, // 9451 + {0.599609f, 0.482422f, 0.615234f, 0.497070f, -1.1250f, -29.3750f, 30.0000f, 32, 30}, // 9451 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9452 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9453 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9454 @@ -19216,7 +19517,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94ad - {0.514648f, 0.539063f, 0.529785f, 0.553711f, -0.8750f, -28.8125f, 30.0000f, 31, 30}, // 94ae + {0.183594f, 0.564941f, 0.198730f, 0.579590f, -0.8750f, -28.8125f, 30.0000f, 31, 30}, // 94ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94b1 @@ -19298,7 +19599,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 94ff - {0.272461f, 0.335938f, 0.287598f, 0.351563f, -0.8750f, -29.0000f, 30.0000f, 31, 32}, // 9500 + {0.655762f, 0.358887f, 0.670898f, 0.374512f, -0.8750f, -29.0000f, 30.0000f, 31, 32}, // 9500 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9501 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9502 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9503 @@ -19323,7 +19624,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9516 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9517 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9518 - {0.078125f, 0.412598f, 0.093262f, 0.427734f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 9519 + {0.459473f, 0.430664f, 0.474609f, 0.445801f, -0.5625f, -28.8750f, 30.0000f, 31, 31}, // 9519 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 951a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 951b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 951c @@ -19344,8 +19645,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 952b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 952c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 952d - {0.769043f, 0.335938f, 0.784668f, 0.351074f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 952e - {0.785156f, 0.335938f, 0.800293f, 0.351563f, -0.7500f, -28.8750f, 30.0000f, 31, 32}, // 952f + {0.318359f, 0.359375f, 0.333984f, 0.374512f, -0.6875f, -28.8125f, 30.0000f, 32, 31}, // 952e + {0.786133f, 0.359863f, 0.801270f, 0.375488f, -0.7500f, -28.8750f, 30.0000f, 31, 32}, // 952f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9530 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9531 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9532 @@ -19390,7 +19691,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9559 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 955a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 955b - {0.744629f, 0.161133f, 0.760254f, 0.176758f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 955c + {0.947266f, 0.180664f, 0.962891f, 0.196289f, -0.8750f, -29.1250f, 30.0000f, 32, 32}, // 955c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 955d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 955e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 955f @@ -19417,7 +19718,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9574 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9575 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9576 - {0.315918f, 0.412598f, 0.331055f, 0.427734f, 0.0625f, -28.0000f, 30.0000f, 31, 31}, // 9577 + {0.284668f, 0.431152f, 0.299805f, 0.446289f, 0.0625f, -28.0000f, 30.0000f, 31, 31}, // 9577 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9578 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9579 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 957a @@ -19426,7 +19727,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 957d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 957e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 957f - {0.436035f, 0.679199f, 0.449219f, 0.693848f, 1.3125f, -27.5000f, 30.0000f, 27, 30}, // 9580 + {0.371094f, 0.719238f, 0.384277f, 0.733887f, 1.3125f, -27.5000f, 30.0000f, 27, 30}, // 9580 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9581 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9582 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9583 @@ -19435,17 +19736,17 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9586 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9587 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9588 - {0.451660f, 0.664551f, 0.465332f, 0.679199f, 1.2500f, -27.5625f, 30.0000f, 28, 30}, // 9589 + {0.713379f, 0.703125f, 0.727051f, 0.717773f, 1.2500f, -27.5625f, 30.0000f, 28, 30}, // 9589 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 958a - {0.484863f, 0.664551f, 0.498535f, 0.679199f, 1.3125f, -28.1875f, 30.0000f, 28, 30}, // 958b + {0.327148f, 0.703613f, 0.340820f, 0.718262f, 1.3125f, -28.1875f, 30.0000f, 28, 30}, // 958b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 958c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 958d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 958e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 958f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9590 - {0.407227f, 0.679688f, 0.420410f, 0.694336f, 1.8750f, -27.9375f, 30.0000f, 27, 30}, // 9591 + {0.474609f, 0.719238f, 0.487793f, 0.733887f, 1.8750f, -27.9375f, 30.0000f, 27, 30}, // 9591 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9592 - {0.575195f, 0.664551f, 0.588867f, 0.679199f, 1.7500f, -27.5625f, 30.0000f, 28, 30}, // 9593 + {0.447754f, 0.703613f, 0.461426f, 0.718262f, 1.7500f, -27.5625f, 30.0000f, 28, 30}, // 9593 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9594 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9595 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9596 @@ -19460,10 +19761,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 959f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a1 - {0.449707f, 0.679688f, 0.462891f, 0.694336f, 1.9375f, -27.6875f, 30.0000f, 27, 30}, // 95a2 - {0.844238f, 0.664551f, 0.857910f, 0.679199f, 1.3750f, -27.9375f, 30.0000f, 28, 30}, // 95a3 + {0.503906f, 0.719238f, 0.517090f, 0.733887f, 1.9375f, -27.6875f, 30.0000f, 27, 30}, // 95a2 + {0.616699f, 0.703613f, 0.630371f, 0.718262f, 1.3750f, -27.9375f, 30.0000f, 28, 30}, // 95a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a4 - {0.478027f, 0.679688f, 0.491211f, 0.694336f, 1.7500f, -27.8750f, 30.0000f, 27, 30}, // 95a5 + {0.488281f, 0.719727f, 0.501465f, 0.734375f, 1.7500f, -27.8750f, 30.0000f, 27, 30}, // 95a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95a8 @@ -19476,7 +19777,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95b1 - {0.014160f, 0.665039f, 0.027832f, 0.679688f, 1.3125f, -28.0625f, 30.0000f, 28, 30}, // 95b2 + {0.104004f, 0.704102f, 0.117676f, 0.718750f, 1.3125f, -28.0625f, 30.0000f, 28, 30}, // 95b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95b5 @@ -19514,11 +19815,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95d7 - {0.572754f, 0.679688f, 0.585938f, 0.694336f, 1.9375f, -27.6875f, 30.0000f, 27, 30}, // 95d8 + {0.576172f, 0.719727f, 0.589355f, 0.734375f, 1.9375f, -27.6875f, 30.0000f, 27, 30}, // 95d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95db - {0.000000f, 0.665527f, 0.013672f, 0.680176f, 1.1250f, -27.8125f, 30.0000f, 28, 30}, // 95dc + {0.118164f, 0.704102f, 0.131836f, 0.718750f, 1.1250f, -27.8125f, 30.0000f, 28, 30}, // 95dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95df @@ -19535,14 +19836,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95ec - {0.091309f, 0.668945f, 0.104492f, 0.684082f, 1.1875f, -28.6250f, 30.0000f, 27, 31}, // 95ed - {0.841797f, 0.679688f, 0.854980f, 0.694336f, 1.3750f, -28.0625f, 30.0000f, 27, 30}, // 95ee + {0.630859f, 0.704590f, 0.644043f, 0.719727f, 1.1875f, -28.6250f, 30.0000f, 27, 31}, // 95ed + {0.068359f, 0.720215f, 0.081543f, 0.734863f, 1.3750f, -28.0625f, 30.0000f, 27, 30}, // 95ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f3 - {0.104980f, 0.668945f, 0.118164f, 0.684082f, 1.0000f, -28.6250f, 30.0000f, 27, 31}, // 95f4 + {0.014160f, 0.705078f, 0.027344f, 0.720215f, 1.0000f, -28.6250f, 30.0000f, 27, 31}, // 95f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 95f7 @@ -19585,7 +19886,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 961c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 961d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 961e - {0.624023f, 0.539063f, 0.638672f, 0.554199f, 1.0000f, -28.9375f, 30.0000f, 30, 31}, // 961f + {0.061523f, 0.564941f, 0.076172f, 0.580078f, 1.0000f, -28.9375f, 30.0000f, 30, 31}, // 961f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9620 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9621 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9622 @@ -19604,7 +19905,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 962f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9630 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9631 - {0.731445f, 0.460449f, 0.746094f, 0.476074f, 1.0625f, -28.8750f, 30.0000f, 30, 32}, // 9632 + {0.345703f, 0.482910f, 0.360352f, 0.498535f, 1.0625f, -28.8750f, 30.0000f, 30, 32}, // 9632 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9633 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9634 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9635 @@ -19613,7 +19914,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9638 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9639 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 963a - {0.244141f, 0.588379f, 0.258789f, 0.603027f, 0.8750f, -27.5000f, 30.0000f, 30, 30}, // 963b + {0.890625f, 0.618652f, 0.905273f, 0.633301f, 0.8750f, -27.5000f, 30.0000f, 30, 30}, // 963b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 963c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 963d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 963e @@ -19622,7 +19923,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9641 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9642 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9643 - {0.746582f, 0.460449f, 0.761230f, 0.476074f, 1.3125f, -29.3125f, 30.0000f, 30, 32}, // 9644 + {0.094727f, 0.483398f, 0.109375f, 0.499023f, 1.3125f, -29.3125f, 30.0000f, 30, 32}, // 9644 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9645 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9646 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9647 @@ -19631,10 +19932,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 964a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 964b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 964c - {0.795898f, 0.460449f, 0.810547f, 0.476074f, 1.0000f, -29.4375f, 30.0000f, 30, 32}, // 964d + {0.300293f, 0.483887f, 0.314941f, 0.499512f, 1.0000f, -29.4375f, 30.0000f, 30, 32}, // 964d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 964e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 964f - {0.118164f, 0.647949f, 0.132324f, 0.662598f, 1.3750f, -27.8750f, 30.0000f, 29, 30}, // 9650 + {0.392090f, 0.677734f, 0.406250f, 0.692383f, 1.3750f, -27.8750f, 30.0000f, 29, 30}, // 9650 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9651 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9652 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9653 @@ -19645,41 +19946,41 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9658 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9659 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 965a - {0.586914f, 0.412598f, 0.602051f, 0.427734f, 0.8125f, -28.8125f, 30.0000f, 31, 31}, // 965b + {0.813477f, 0.431152f, 0.828613f, 0.446289f, 0.8125f, -28.8125f, 30.0000f, 31, 31}, // 965b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 965c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 965d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 965e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 965f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9660 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9661 - {0.093750f, 0.460938f, 0.108398f, 0.476563f, 1.0000f, -28.9375f, 30.0000f, 30, 32}, // 9662 - {0.124023f, 0.460938f, 0.138672f, 0.476563f, 1.0625f, -29.0625f, 30.0000f, 30, 32}, // 9663 - {0.233887f, 0.460938f, 0.248535f, 0.476563f, 1.3125f, -29.6250f, 30.0000f, 30, 32}, // 9664 - {0.245605f, 0.556152f, 0.259766f, 0.571777f, 1.1875f, -29.5625f, 30.0000f, 29, 32}, // 9665 + {0.315430f, 0.483887f, 0.330078f, 0.499512f, 1.0000f, -28.9375f, 30.0000f, 30, 32}, // 9662 + {0.360840f, 0.483887f, 0.375488f, 0.499512f, 1.0625f, -29.0625f, 30.0000f, 30, 32}, // 9663 + {0.631836f, 0.483887f, 0.646484f, 0.499512f, 1.3125f, -29.6250f, 30.0000f, 30, 32}, // 9664 + {0.717773f, 0.585449f, 0.731934f, 0.601074f, 1.1875f, -29.5625f, 30.0000f, 29, 32}, // 9665 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9666 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9667 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9668 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9669 - {0.505371f, 0.460938f, 0.520020f, 0.476563f, 0.8750f, -29.0625f, 30.0000f, 30, 32}, // 966a + {0.772461f, 0.483887f, 0.787109f, 0.499512f, 0.8750f, -29.0625f, 30.0000f, 30, 32}, // 966a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 966b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 966c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 966d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 966e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 966f - {0.520508f, 0.460938f, 0.535156f, 0.476563f, 1.3125f, -29.3125f, 30.0000f, 30, 32}, // 9670 + {0.787598f, 0.483887f, 0.802246f, 0.499512f, 1.3125f, -29.3125f, 30.0000f, 30, 32}, // 9670 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9671 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9672 - {0.635254f, 0.460938f, 0.649902f, 0.476563f, 1.1250f, -28.8125f, 30.0000f, 30, 32}, // 9673 + {0.203125f, 0.485840f, 0.217773f, 0.501465f, 1.1250f, -28.8125f, 30.0000f, 30, 32}, // 9673 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9674 - {0.816406f, 0.335938f, 0.831543f, 0.351563f, 0.8125f, -29.0000f, 30.0000f, 31, 32}, // 9675 - {0.134766f, 0.617188f, 0.148926f, 0.632324f, 1.4375f, -29.1250f, 30.0000f, 29, 31}, // 9676 + {0.206055f, 0.360840f, 0.221191f, 0.376465f, 0.8125f, -29.0000f, 30.0000f, 31, 32}, // 9675 + {0.395508f, 0.645996f, 0.409668f, 0.661133f, 1.4375f, -29.1250f, 30.0000f, 29, 31}, // 9676 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9677 - {0.718750f, 0.539063f, 0.733398f, 0.554199f, 1.0625f, -29.0000f, 30.0000f, 30, 31}, // 9678 + {0.465820f, 0.564941f, 0.480469f, 0.580078f, 1.0625f, -29.0000f, 30.0000f, 30, 31}, // 9678 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9679 - {0.779785f, 0.460938f, 0.794434f, 0.476563f, 0.9375f, -29.4375f, 30.0000f, 30, 32}, // 967a + {0.032227f, 0.486328f, 0.046875f, 0.501953f, 0.9375f, -29.4375f, 30.0000f, 30, 32}, // 967a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 967b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 967c - {0.354492f, 0.588379f, 0.369141f, 0.603027f, 0.6250f, -27.3750f, 30.0000f, 30, 30}, // 967d + {0.875000f, 0.619629f, 0.889648f, 0.634277f, 0.6250f, -27.3750f, 30.0000f, 30, 30}, // 967d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 967e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 967f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9680 @@ -19687,37 +19988,37 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9682 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9683 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9684 - {0.363770f, 0.647949f, 0.377930f, 0.662598f, 0.9375f, -28.0000f, 30.0000f, 29, 30}, // 9685 - {0.894043f, 0.335938f, 0.909180f, 0.351563f, 0.7500f, -29.5000f, 30.0000f, 31, 32}, // 9686 + {0.208984f, 0.678223f, 0.223145f, 0.692871f, 0.9375f, -28.0000f, 30.0000f, 29, 30}, // 9685 + {0.492188f, 0.360840f, 0.507324f, 0.376465f, 0.7500f, -29.5000f, 30.0000f, 31, 32}, // 9686 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9687 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9688 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9689 - {0.951660f, 0.460938f, 0.966309f, 0.476563f, 1.0000f, -29.1250f, 30.0000f, 30, 32}, // 968a + {0.047363f, 0.486328f, 0.062012f, 0.501953f, 1.0000f, -29.1250f, 30.0000f, 30, 32}, // 968a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 968b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 968c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 968d - {0.733887f, 0.539063f, 0.748535f, 0.554199f, 1.0000f, -29.0000f, 30.0000f, 30, 31}, // 968e - {0.771484f, 0.539063f, 0.786133f, 0.554199f, 0.9375f, -28.8125f, 30.0000f, 30, 31}, // 968f + {0.529297f, 0.564941f, 0.543945f, 0.580078f, 1.0000f, -29.0000f, 30.0000f, 30, 31}, // 968e + {0.544434f, 0.564941f, 0.559082f, 0.580078f, 0.9375f, -28.8125f, 30.0000f, 30, 31}, // 968f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9690 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9691 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9692 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9693 - {0.856445f, 0.588379f, 0.871094f, 0.603027f, 0.8750f, -28.0625f, 30.0000f, 30, 30}, // 9694 + {0.305176f, 0.621094f, 0.319824f, 0.635742f, 0.8750f, -28.0625f, 30.0000f, 30, 30}, // 9694 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9695 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9696 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9697 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9698 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9699 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 969a - {0.966797f, 0.460938f, 0.981445f, 0.476563f, 0.7500f, -29.2500f, 30.0000f, 30, 32}, // 969b - {0.092773f, 0.539551f, 0.107422f, 0.554688f, 0.8125f, -28.9375f, 30.0000f, 30, 31}, // 969c + {0.078613f, 0.486328f, 0.093262f, 0.501953f, 0.7500f, -29.2500f, 30.0000f, 30, 32}, // 969b + {0.015137f, 0.565430f, 0.029785f, 0.580566f, 0.8125f, -28.9375f, 30.0000f, 30, 31}, // 969c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 969d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 969e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 969f - {0.981934f, 0.460938f, 0.996582f, 0.476563f, 1.3750f, -29.1875f, 30.0000f, 30, 32}, // 96a0 + {0.187500f, 0.486328f, 0.202148f, 0.501953f, 1.3750f, -29.1875f, 30.0000f, 30, 32}, // 96a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96a2 - {0.139160f, 0.461426f, 0.153809f, 0.477051f, 1.0000f, -29.0000f, 30.0000f, 30, 32}, // 96a3 + {0.486328f, 0.486328f, 0.500977f, 0.501953f, 1.0000f, -29.0000f, 30.0000f, 30, 32}, // 96a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96a6 @@ -19737,11 +20038,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96b6 - {0.760742f, 0.161133f, 0.776367f, 0.176758f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 96b7 + {0.963379f, 0.180664f, 0.979004f, 0.196289f, -0.6250f, -28.9375f, 30.0000f, 32, 32}, // 96b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ba - {0.649902f, 0.032227f, 0.666016f, 0.047852f, -1.0625f, -29.3750f, 30.0000f, 33, 32}, // 96bb + {0.543457f, 0.048828f, 0.559570f, 0.064453f, -1.0625f, -29.3750f, 30.0000f, 33, 32}, // 96bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96be @@ -19750,20 +20051,20 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96c3 - {0.925781f, 0.335938f, 0.941406f, 0.351074f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 96c4 - {0.957520f, 0.335938f, 0.973145f, 0.351074f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 96c5 - {0.239258f, 0.336426f, 0.254883f, 0.351563f, -0.3750f, -28.9375f, 30.0000f, 32, 31}, // 96c6 - {0.638184f, 0.412598f, 0.653320f, 0.427734f, -1.1250f, -28.5625f, 30.0000f, 31, 31}, // 96c7 + {0.507813f, 0.360840f, 0.523438f, 0.375977f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 96c4 + {0.637695f, 0.360840f, 0.653320f, 0.375977f, -0.6250f, -29.1250f, 30.0000f, 32, 31}, // 96c5 + {0.687988f, 0.360840f, 0.703613f, 0.375977f, -0.3750f, -28.9375f, 30.0000f, 32, 31}, // 96c6 + {0.300293f, 0.431641f, 0.315430f, 0.446777f, -1.1250f, -28.5625f, 30.0000f, 31, 31}, // 96c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96cb - {0.776855f, 0.161133f, 0.792480f, 0.176758f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 96cc + {0.979492f, 0.180664f, 0.995117f, 0.196289f, -1.0000f, -29.0000f, 30.0000f, 32, 32}, // 96cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96cf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96d0 - {0.351563f, 0.336426f, 0.367188f, 0.351563f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 96d1 + {0.770508f, 0.360840f, 0.786133f, 0.375977f, -0.8750f, -29.0625f, 30.0000f, 32, 31}, // 96d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96d4 @@ -19780,47 +20081,47 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e1 - {0.445313f, 0.336426f, 0.460449f, 0.352051f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 96e2 - {0.792969f, 0.161133f, 0.808594f, 0.176758f, -0.7500f, -29.0625f, 30.0000f, 32, 32}, // 96e3 + {0.175293f, 0.361328f, 0.190430f, 0.376953f, -0.0625f, -29.0625f, 30.0000f, 31, 32}, // 96e2 + {0.852539f, 0.181152f, 0.868164f, 0.196777f, -0.7500f, -29.0625f, 30.0000f, 32, 32}, // 96e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e7 - {0.273926f, 0.588867f, 0.288574f, 0.603516f, 0.4375f, -27.3125f, 30.0000f, 30, 30}, // 96e8 + {0.350586f, 0.621094f, 0.365234f, 0.635742f, 0.4375f, -27.3125f, 30.0000f, 30, 30}, // 96e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96e9 - {0.846680f, 0.648926f, 0.860352f, 0.664063f, 0.8750f, -28.0000f, 30.0000f, 28, 31}, // 96ea + {0.900391f, 0.683594f, 0.914063f, 0.698730f, 0.8750f, -28.0000f, 30.0000f, 28, 31}, // 96ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96eb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ef - {0.623535f, 0.336426f, 0.639160f, 0.351563f, -0.6875f, -28.6250f, 30.0000f, 32, 31}, // 96f0 + {0.541016f, 0.361328f, 0.556641f, 0.376465f, -0.6875f, -28.6250f, 30.0000f, 32, 31}, // 96f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f1 - {0.123047f, 0.539551f, 0.137695f, 0.554688f, 0.3125f, -28.1875f, 30.0000f, 30, 31}, // 96f2 + {0.076660f, 0.565430f, 0.091309f, 0.580566f, 0.3125f, -28.1875f, 30.0000f, 30, 31}, // 96f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f5 - {0.655273f, 0.336426f, 0.670898f, 0.351563f, -0.7500f, -28.3125f, 30.0000f, 32, 31}, // 96f6 - {0.641113f, 0.647949f, 0.655273f, 0.662598f, 1.1250f, -27.6250f, 30.0000f, 29, 30}, // 96f7 + {0.557129f, 0.361328f, 0.572754f, 0.376465f, -0.7500f, -28.3125f, 30.0000f, 32, 31}, // 96f6 + {0.406738f, 0.678223f, 0.420898f, 0.692871f, 1.1250f, -27.6250f, 30.0000f, 29, 30}, // 96f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96fa - {0.681152f, 0.588867f, 0.695801f, 0.603516f, 0.5625f, -28.0625f, 30.0000f, 30, 30}, // 96fb + {0.821777f, 0.621094f, 0.836426f, 0.635742f, 0.5625f, -28.0625f, 30.0000f, 30, 30}, // 96fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 96ff - {0.182617f, 0.589355f, 0.197266f, 0.604004f, 0.3750f, -27.6250f, 30.0000f, 30, 30}, // 9700 + {0.665039f, 0.621582f, 0.679688f, 0.636230f, 0.3750f, -27.6250f, 30.0000f, 30, 30}, // 9700 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9701 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9702 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9703 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9704 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9705 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9706 - {0.704590f, 0.336426f, 0.720215f, 0.351563f, -1.0000f, -28.2500f, 30.0000f, 32, 31}, // 9707 + {0.671387f, 0.361328f, 0.687012f, 0.376465f, -1.0000f, -28.2500f, 30.0000f, 32, 31}, // 9707 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9708 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9709 - {0.831543f, 0.647949f, 0.846191f, 0.662109f, 0.2500f, -27.3750f, 30.0000f, 30, 29}, // 970a + {0.255371f, 0.678711f, 0.270020f, 0.692871f, 0.2500f, -27.3750f, 30.0000f, 30, 29}, // 970a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 970b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 970c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 970d @@ -19838,7 +20139,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9719 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 971a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 971b - {0.319824f, 0.589355f, 0.334473f, 0.604004f, -0.1250f, -27.5625f, 30.0000f, 30, 30}, // 971c + {0.970703f, 0.621582f, 0.985352f, 0.636230f, -0.1250f, -27.5625f, 30.0000f, 30, 30}, // 971c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 971d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 971e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 971f @@ -19849,7 +20150,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9724 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9725 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9726 - {0.909668f, 0.336426f, 0.925293f, 0.351563f, -0.5000f, -28.6875f, 30.0000f, 32, 31}, // 9727 + {0.048340f, 0.361816f, 0.063965f, 0.376953f, -0.5000f, -28.6875f, 30.0000f, 32, 31}, // 9727 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9728 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9729 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 972a @@ -19860,7 +20161,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 972f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9730 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9731 - {0.686523f, 0.412598f, 0.701660f, 0.427734f, 0.0625f, -28.5625f, 30.0000f, 31, 31}, // 9732 + {0.927246f, 0.431641f, 0.942383f, 0.446777f, 0.0625f, -28.5625f, 30.0000f, 31, 31}, // 9732 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9733 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9734 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9735 @@ -19882,7 +20183,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9745 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9746 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9747 - {0.939453f, 0.647949f, 0.954102f, 0.662109f, 0.1875f, -27.3750f, 30.0000f, 30, 29}, // 9748 + {0.668457f, 0.678711f, 0.683105f, 0.692871f, 0.1875f, -27.3750f, 30.0000f, 30, 29}, // 9748 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9749 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 974a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 974b @@ -19892,30 +20193,30 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 974f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9750 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9751 - {0.369629f, 0.556152f, 0.383789f, 0.571777f, 1.0625f, -29.1250f, 30.0000f, 29, 32}, // 9752 + {0.816895f, 0.585938f, 0.831055f, 0.601563f, 1.0625f, -29.1250f, 30.0000f, 29, 32}, // 9752 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9753 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9754 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9755 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9756 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9757 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9758 - {0.717773f, 0.412598f, 0.732910f, 0.427734f, 0.0625f, -29.0625f, 30.0000f, 31, 31}, // 9759 + {0.942871f, 0.431641f, 0.958008f, 0.446777f, 0.0625f, -29.0625f, 30.0000f, 31, 31}, // 9759 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 975a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 975b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 975c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 975d - {0.733398f, 0.412598f, 0.748535f, 0.427734f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 975e + {0.958496f, 0.431641f, 0.973633f, 0.446777f, -0.5625f, -28.8125f, 30.0000f, 31, 31}, // 975e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 975f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9760 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9761 - {0.334961f, 0.591797f, 0.349609f, 0.606445f, 0.0625f, -27.5625f, 30.0000f, 30, 30}, // 9762 + {0.242676f, 0.622070f, 0.257324f, 0.636719f, 0.0625f, -27.5625f, 30.0000f, 30, 30}, // 9762 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9763 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9764 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9765 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9766 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9767 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9768 - {0.229980f, 0.539551f, 0.244629f, 0.554688f, 0.1875f, -28.8750f, 30.0000f, 30, 31}, // 9769 + {0.122559f, 0.565430f, 0.137207f, 0.580566f, 0.1875f, -28.8750f, 30.0000f, 30, 31}, // 9769 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 976a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 976b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 976c @@ -19926,7 +20227,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9771 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9772 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9773 - {0.190918f, 0.336914f, 0.206543f, 0.352051f, -0.6875f, -28.7500f, 30.0000f, 32, 31}, // 9774 + {0.573242f, 0.361816f, 0.588867f, 0.376953f, -0.6875f, -28.7500f, 30.0000f, 32, 31}, // 9774 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9775 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9776 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9777 @@ -20053,7 +20354,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f2 - {0.456543f, 0.461426f, 0.471191f, 0.477051f, 0.1250f, -29.1875f, 30.0000f, 30, 32}, // 97f3 + {0.615723f, 0.486328f, 0.630371f, 0.501953f, 0.1250f, -29.1875f, 30.0000f, 30, 32}, // 97f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f6 @@ -20061,18 +20362,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97fa - {0.498047f, 0.336426f, 0.513184f, 0.352051f, -0.0625f, -29.2500f, 30.0000f, 31, 32}, // 97fb + {0.190918f, 0.361328f, 0.206055f, 0.376953f, -0.0625f, -29.2500f, 30.0000f, 31, 32}, // 97fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 97fe - {0.255371f, 0.336914f, 0.270508f, 0.352539f, -0.1250f, -29.3750f, 30.0000f, 31, 32}, // 97ff + {0.080078f, 0.362305f, 0.095215f, 0.377930f, -0.1250f, -29.3750f, 30.0000f, 31, 32}, // 97ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9800 - {0.000000f, 0.593262f, 0.014648f, 0.607910f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // 9801 - {0.403320f, 0.539551f, 0.418457f, 0.554199f, 0.2500f, -27.7500f, 30.0000f, 31, 30}, // 9802 + {0.425293f, 0.622070f, 0.439941f, 0.636719f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // 9801 + {0.152832f, 0.565430f, 0.167969f, 0.580078f, 0.2500f, -27.7500f, 30.0000f, 31, 30}, // 9802 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9803 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9804 - {0.467285f, 0.539551f, 0.482422f, 0.554199f, -0.5625f, -27.5625f, 30.0000f, 31, 30}, // 9805 - {0.093750f, 0.413086f, 0.108887f, 0.428223f, -0.1875f, -28.0625f, 30.0000f, 31, 31}, // 9806 + {0.480957f, 0.565430f, 0.496094f, 0.580078f, -0.5625f, -27.5625f, 30.0000f, 31, 30}, // 9805 + {0.974121f, 0.431641f, 0.989258f, 0.446777f, -0.1875f, -28.0625f, 30.0000f, 31, 31}, // 9806 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9807 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9808 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9809 @@ -20082,15 +20383,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 980d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 980e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 980f - {0.471680f, 0.461426f, 0.487305f, 0.476074f, -0.4375f, -27.4375f, 30.0000f, 32, 30}, // 9810 - {0.207031f, 0.337891f, 0.222656f, 0.353027f, -0.7500f, -27.6875f, 30.0000f, 32, 31}, // 9811 - {0.223145f, 0.337891f, 0.238770f, 0.353027f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 9812 - {0.809082f, 0.161133f, 0.824707f, 0.176758f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 9813 + {0.663086f, 0.486328f, 0.678711f, 0.500977f, -0.4375f, -27.4375f, 30.0000f, 32, 30}, // 9810 + {0.143555f, 0.362305f, 0.159180f, 0.377441f, -0.7500f, -27.6875f, 30.0000f, 32, 31}, // 9811 + {0.589355f, 0.362305f, 0.604980f, 0.377441f, -0.6250f, -28.6875f, 30.0000f, 32, 31}, // 9812 + {0.892090f, 0.181641f, 0.907715f, 0.197266f, -0.4375f, -29.0625f, 30.0000f, 32, 32}, // 9813 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9814 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9815 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9816 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9817 - {0.843750f, 0.161133f, 0.859375f, 0.176758f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 9818 + {0.096680f, 0.182617f, 0.112305f, 0.198242f, -0.8125f, -29.1875f, 30.0000f, 32, 32}, // 9818 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9819 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 981a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 981b @@ -20111,7 +20412,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 982a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 982b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 982c - {0.249023f, 0.461914f, 0.264648f, 0.476563f, -0.5000f, -27.6250f, 30.0000f, 32, 30}, // 982d + {0.470703f, 0.486816f, 0.486328f, 0.501465f, -0.5000f, -27.6250f, 30.0000f, 32, 30}, // 982d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 982e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 982f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9830 @@ -20125,8 +20426,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9838 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9839 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 983a - {0.859863f, 0.161133f, 0.875488f, 0.176758f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 983b - {0.875977f, 0.161133f, 0.891602f, 0.176758f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 983c + {0.112793f, 0.182617f, 0.128418f, 0.198242f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 983b + {0.128906f, 0.183105f, 0.144531f, 0.198730f, -0.6875f, -28.8750f, 30.0000f, 32, 32}, // 983c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 983d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 983e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 983f @@ -20142,25 +20443,25 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9849 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 984a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 984b - {0.329590f, 0.461914f, 0.345215f, 0.476563f, -0.8125f, -27.6250f, 30.0000f, 32, 30}, // 984c - {0.413086f, 0.337891f, 0.428711f, 0.353027f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 984d + {0.518555f, 0.486816f, 0.534180f, 0.501465f, -0.8125f, -27.6250f, 30.0000f, 32, 30}, // 984c + {0.605469f, 0.362793f, 0.621094f, 0.377930f, -0.8125f, -28.7500f, 30.0000f, 32, 31}, // 984d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 984e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 984f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9850 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9851 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9852 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9853 - {0.460938f, 0.337891f, 0.476563f, 0.353027f, -1.0625f, -28.9375f, 30.0000f, 32, 31}, // 9854 - {0.603027f, 0.461914f, 0.618652f, 0.476563f, -0.6875f, -27.5000f, 30.0000f, 32, 30}, // 9855 + {0.064453f, 0.363281f, 0.080078f, 0.378418f, -1.0625f, -28.9375f, 30.0000f, 32, 31}, // 9854 + {0.568848f, 0.486816f, 0.584473f, 0.501465f, -0.6875f, -27.5000f, 30.0000f, 32, 30}, // 9855 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9856 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9857 - {0.859375f, 0.461914f, 0.875000f, 0.476563f, -0.9375f, -27.9375f, 30.0000f, 32, 30}, // 9858 + {0.062500f, 0.487793f, 0.078125f, 0.502441f, -0.9375f, -27.9375f, 30.0000f, 32, 30}, // 9858 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9859 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 985a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 985b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 985c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 985d - {0.477051f, 0.337891f, 0.492676f, 0.353027f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 985e + {0.111816f, 0.363281f, 0.127441f, 0.378418f, -0.8750f, -28.8750f, 30.0000f, 32, 31}, // 985e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 985f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9860 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9861 @@ -20169,7 +20470,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9864 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9865 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9866 - {0.304688f, 0.340332f, 0.320313f, 0.355469f, -0.8125f, -28.6250f, 30.0000f, 32, 31}, // 9867 + {0.159668f, 0.363770f, 0.175293f, 0.378906f, -0.8125f, -28.6250f, 30.0000f, 32, 31}, // 9867 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9868 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9869 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 986a @@ -20177,23 +20478,23 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 986c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 986d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 986e - {0.377930f, 0.462402f, 0.393555f, 0.477051f, -0.7500f, -27.6250f, 30.0000f, 32, 30}, // 986f + {0.534668f, 0.487793f, 0.550293f, 0.502441f, -0.7500f, -27.6250f, 30.0000f, 32, 30}, // 986f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9870 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9871 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9872 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9873 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9874 - {0.954590f, 0.647949f, 0.968750f, 0.662598f, 0.3125f, -27.2500f, 30.0000f, 29, 30}, // 9875 - {0.498535f, 0.539551f, 0.513672f, 0.554199f, -0.6250f, -27.5000f, 30.0000f, 31, 30}, // 9876 + {0.000000f, 0.679199f, 0.014160f, 0.693848f, 0.3125f, -27.2500f, 30.0000f, 29, 30}, // 9875 + {0.606934f, 0.565430f, 0.622070f, 0.580078f, -0.6250f, -27.5000f, 30.0000f, 31, 30}, // 9876 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9877 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9878 - {0.591797f, 0.539551f, 0.606934f, 0.554199f, -0.8750f, -27.3750f, 30.0000f, 31, 30}, // 9879 + {0.137695f, 0.565918f, 0.152832f, 0.580566f, -0.8750f, -27.3750f, 30.0000f, 31, 30}, // 9879 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 987a - {0.367676f, 0.342773f, 0.383301f, 0.357910f, -1.1250f, -28.2500f, 30.0000f, 32, 31}, // 987b + {0.000000f, 0.364258f, 0.015625f, 0.379395f, -1.1250f, -28.2500f, 30.0000f, 32, 31}, // 987b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 987c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 987d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 987e - {0.524902f, 0.413086f, 0.540039f, 0.428223f, -0.2500f, -29.0000f, 30.0000f, 31, 31}, // 987f + {0.845703f, 0.432129f, 0.860840f, 0.447266f, -0.2500f, -29.0000f, 30.0000f, 31, 31}, // 987f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9880 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9881 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9882 @@ -20211,18 +20512,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 988e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 988f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9890 - {0.383789f, 0.343262f, 0.399414f, 0.358398f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 9891 + {0.016113f, 0.364258f, 0.031738f, 0.379395f, -0.5000f, -28.7500f, 30.0000f, 32, 31}, // 9891 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9892 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9893 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9894 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9895 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9896 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9897 - {0.439453f, 0.462402f, 0.455078f, 0.477051f, -1.0625f, -27.6875f, 30.0000f, 32, 30}, // 9898 + {0.646973f, 0.487793f, 0.662598f, 0.502441f, -1.0625f, -27.6875f, 30.0000f, 32, 30}, // 9898 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9899 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 989a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 989b - {0.892090f, 0.161133f, 0.907715f, 0.176758f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 989c + {0.743652f, 0.183105f, 0.759277f, 0.198730f, -1.1250f, -29.0000f, 30.0000f, 32, 32}, // 989c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 989d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 989e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 989f @@ -20234,7 +20535,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98a7 - {0.265137f, 0.462891f, 0.280762f, 0.477539f, -0.5000f, -27.5000f, 30.0000f, 32, 30}, // 98a8 + {0.140625f, 0.488281f, 0.156250f, 0.502930f, -0.5000f, -27.5000f, 30.0000f, 32, 30}, // 98a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98ab @@ -20285,14 +20586,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98da - {0.696289f, 0.462891f, 0.711914f, 0.477539f, -0.1250f, -27.6250f, 30.0000f, 32, 30}, // 98db + {0.156738f, 0.488281f, 0.172363f, 0.502930f, -0.1250f, -27.6250f, 30.0000f, 32, 30}, // 98db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98de - {0.908203f, 0.161133f, 0.923828f, 0.176758f, -0.7500f, -29.4375f, 30.0000f, 32, 32}, // 98df + {0.386719f, 0.183594f, 0.402344f, 0.199219f, -0.7500f, -29.4375f, 30.0000f, 32, 32}, // 98df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98e1 - {0.111328f, 0.343750f, 0.126953f, 0.358887f, -1.0625f, -29.1875f, 30.0000f, 32, 31}, // 98e2 + {0.127930f, 0.364258f, 0.143555f, 0.379395f, -1.0625f, -29.1875f, 30.0000f, 32, 31}, // 98e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98e3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98e5 @@ -20305,10 +20606,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98ee - {0.924316f, 0.161133f, 0.939941f, 0.176758f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 98ef + {0.402832f, 0.183594f, 0.418457f, 0.199219f, -1.0000f, -29.1875f, 30.0000f, 32, 32}, // 98ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f1 - {0.666504f, 0.032227f, 0.682617f, 0.047852f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 98f2 + {0.560059f, 0.048828f, 0.576172f, 0.064453f, -1.0000f, -29.1875f, 30.0000f, 33, 32}, // 98f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f5 @@ -20318,9 +20619,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98fb - {0.000000f, 0.344238f, 0.015137f, 0.359863f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 98fc - {0.015625f, 0.346191f, 0.031250f, 0.361328f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 98fd - {0.940430f, 0.161133f, 0.956055f, 0.176758f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 98fe + {0.738281f, 0.364746f, 0.753418f, 0.380371f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 98fc + {0.221680f, 0.365723f, 0.237305f, 0.380859f, -0.9375f, -29.1875f, 30.0000f, 32, 31}, // 98fd + {0.661133f, 0.183594f, 0.676758f, 0.199219f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 98fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 98ff {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9900 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9901 @@ -20332,7 +20633,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9907 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9908 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9909 - {0.956543f, 0.161133f, 0.972168f, 0.176758f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 990a + {0.354492f, 0.185059f, 0.370117f, 0.200684f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 990a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 990b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 990c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 990d @@ -20341,7 +20642,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9910 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9911 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9912 - {0.048340f, 0.346680f, 0.063965f, 0.361816f, -1.0000f, -29.1875f, 30.0000f, 32, 31}, // 9913 + {0.255371f, 0.365723f, 0.270996f, 0.380859f, -1.0000f, -29.1875f, 30.0000f, 32, 31}, // 9913 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9914 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9915 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9916 @@ -20362,7 +20663,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9925 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9926 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9927 - {0.064453f, 0.346680f, 0.079590f, 0.362305f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 9928 + {0.271484f, 0.365723f, 0.286621f, 0.381348f, -1.0000f, -29.1875f, 30.0000f, 31, 32}, // 9928 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9929 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 992a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 992b @@ -20397,7 +20698,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9948 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9949 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 994a - {0.972656f, 0.161133f, 0.988281f, 0.176758f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 994b + {0.693848f, 0.185059f, 0.709473f, 0.200684f, -0.8750f, -29.3125f, 30.0000f, 32, 32}, // 994b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 994c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 994d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 994e @@ -20458,7 +20759,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9985 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9986 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9987 - {0.031738f, 0.347656f, 0.047363f, 0.362793f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 9988 + {0.720215f, 0.365723f, 0.735840f, 0.380859f, -0.9375f, -28.8750f, 30.0000f, 32, 31}, // 9988 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9989 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 998a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 998b @@ -20472,10 +20773,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9993 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9994 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9995 - {0.863770f, 0.556152f, 0.877930f, 0.571777f, 0.8750f, -29.3125f, 30.0000f, 29, 32}, // 9996 + {0.922363f, 0.585938f, 0.936523f, 0.601563f, 0.8750f, -29.3125f, 30.0000f, 29, 32}, // 9996 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9997 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9998 - {0.288086f, 0.348633f, 0.303711f, 0.363770f, -0.8125f, -28.5625f, 30.0000f, 32, 31}, // 9999 + {0.237793f, 0.367188f, 0.253418f, 0.382324f, -0.8125f, -28.5625f, 30.0000f, 32, 31}, // 9999 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 999a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 999b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 999c @@ -20494,7 +20795,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99ab - {0.104492f, 0.593262f, 0.119141f, 0.607910f, -0.3750f, -27.2500f, 30.0000f, 30, 30}, // 99ac + {0.440430f, 0.622070f, 0.455078f, 0.636719f, -0.3750f, -27.2500f, 30.0000f, 30, 30}, // 99ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99af @@ -20518,9 +20819,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c3 - {0.512207f, 0.161621f, 0.527832f, 0.177246f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 99c4 - {0.875488f, 0.462891f, 0.891113f, 0.477539f, -0.6875f, -27.9375f, 30.0000f, 32, 30}, // 99c5 - {0.891602f, 0.462891f, 0.907227f, 0.477539f, -1.2500f, -28.0000f, 30.0000f, 32, 30}, // 99c6 + {0.810547f, 0.185059f, 0.826172f, 0.200684f, -0.6875f, -29.0000f, 30.0000f, 32, 32}, // 99c4 + {0.550781f, 0.488281f, 0.566406f, 0.502930f, -0.6875f, -27.9375f, 30.0000f, 32, 30}, // 99c5 + {0.000000f, 0.488770f, 0.015625f, 0.503418f, -1.2500f, -28.0000f, 30.0000f, 32, 30}, // 99c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99c9 @@ -20530,7 +20831,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99cf - {0.158691f, 0.349609f, 0.174316f, 0.364746f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 99d0 + {0.032227f, 0.367676f, 0.047852f, 0.382813f, -0.5625f, -28.9375f, 30.0000f, 32, 31}, // 99d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 99d3 @@ -20592,12 +20893,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a0d - {0.174805f, 0.349609f, 0.190430f, 0.364746f, -0.6875f, -29.0625f, 30.0000f, 32, 31}, // 9a0e + {0.442871f, 0.367676f, 0.458496f, 0.382813f, -0.6875f, -29.0625f, 30.0000f, 32, 31}, // 9a0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a11 - {0.203125f, 0.464355f, 0.218750f, 0.479004f, -0.5625f, -27.7500f, 30.0000f, 32, 30}, // 9a12 - {0.652832f, 0.161621f, 0.668457f, 0.177246f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 9a13 + {0.109863f, 0.488770f, 0.125488f, 0.503418f, -0.5625f, -27.7500f, 30.0000f, 32, 30}, // 9a12 + {0.826660f, 0.185547f, 0.842285f, 0.201172f, -0.6250f, -29.1250f, 30.0000f, 32, 32}, // 9a13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a16 @@ -20626,7 +20927,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a2f - {0.825195f, 0.161621f, 0.840820f, 0.177246f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 9a30 + {0.209473f, 0.187012f, 0.225098f, 0.202637f, -0.8125f, -29.2500f, 30.0000f, 32, 32}, // 9a30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a33 @@ -20647,7 +20948,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a44 - {0.297363f, 0.465820f, 0.312988f, 0.480469f, -0.6250f, -27.8750f, 30.0000f, 32, 30}, // 9a45 + {0.250488f, 0.489258f, 0.266113f, 0.503906f, -0.6250f, -27.8750f, 30.0000f, 32, 30}, // 9a45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a48 @@ -20665,10 +20966,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a56 - {0.528320f, 0.162109f, 0.543945f, 0.177734f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 9a57 + {0.225586f, 0.187012f, 0.241211f, 0.202637f, -0.8750f, -29.4375f, 30.0000f, 32, 32}, // 9a57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a59 - {0.273926f, 0.162598f, 0.289551f, 0.178223f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 9a5a + {0.241699f, 0.187012f, 0.257324f, 0.202637f, -0.5000f, -29.3750f, 30.0000f, 32, 32}, // 9a5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a5d @@ -20718,7 +21019,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a8b - {0.561035f, 0.349609f, 0.576660f, 0.364746f, -1.0000f, -29.0625f, 30.0000f, 32, 31}, // 9a8c + {0.458984f, 0.367676f, 0.474609f, 0.382813f, -1.0000f, -29.0625f, 30.0000f, 32, 31}, // 9a8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9a8f @@ -20746,7 +21047,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aa5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aa7 - {0.670410f, 0.666016f, 0.684082f, 0.680664f, 1.0000f, -28.1875f, 30.0000f, 28, 30}, // 9aa8 + {0.476074f, 0.704102f, 0.489746f, 0.718750f, 1.0000f, -28.1875f, 30.0000f, 28, 30}, // 9aa8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aa9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aaa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aab @@ -20774,7 +21075,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac3 - {0.080078f, 0.350098f, 0.095703f, 0.365234f, -0.6250f, -29.1875f, 30.0000f, 32, 31}, // 9ac4 + {0.753906f, 0.367676f, 0.769531f, 0.382813f, -0.6250f, -29.1875f, 30.0000f, 32, 31}, // 9ac4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ac7 @@ -20790,11 +21091,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad3 - {0.936523f, 0.461426f, 0.951172f, 0.477051f, 0.3750f, -28.9375f, 30.0000f, 30, 32}, // 9ad4 + {0.757324f, 0.487305f, 0.771973f, 0.502930f, 0.3750f, -28.9375f, 30.0000f, 30, 32}, // 9ad4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad7 - {0.426758f, 0.617188f, 0.440918f, 0.632324f, 1.0625f, -28.8750f, 30.0000f, 29, 31}, // 9ad8 + {0.211426f, 0.646484f, 0.225586f, 0.661621f, 1.0625f, -28.8750f, 30.0000f, 29, 31}, // 9ad8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ad9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ada {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9adb @@ -20812,7 +21113,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ae7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ae8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ae9 - {0.290039f, 0.162598f, 0.305664f, 0.178223f, -0.5000f, -29.6250f, 30.0000f, 32, 32}, // 9aea + {0.530762f, 0.187012f, 0.546387f, 0.202637f, -0.5000f, -29.6250f, 30.0000f, 32, 32}, // 9aea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aeb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9aed @@ -20871,7 +21172,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b22 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b24 - {0.014648f, 0.649414f, 0.028320f, 0.664551f, 1.4375f, -28.8125f, 30.0000f, 28, 31}, // 9b25 + {0.970215f, 0.683594f, 0.983887f, 0.698730f, 1.4375f, -28.8125f, 30.0000f, 28, 31}, // 9b25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b28 @@ -20894,16 +21195,16 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b3b - {0.306152f, 0.162598f, 0.321777f, 0.178223f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 9b3c + {0.546875f, 0.187012f, 0.562500f, 0.202637f, -0.6875f, -29.5000f, 30.0000f, 32, 32}, // 9b3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b3f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b41 - {0.463379f, 0.162598f, 0.479004f, 0.178223f, -0.6250f, -29.7500f, 30.0000f, 32, 32}, // 9b42 + {0.677246f, 0.187500f, 0.692871f, 0.203125f, -0.6250f, -29.7500f, 30.0000f, 32, 32}, // 9b42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b44 - {0.479492f, 0.162598f, 0.495117f, 0.178223f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 9b45 + {0.709961f, 0.187500f, 0.725586f, 0.203125f, -1.0000f, -29.2500f, 30.0000f, 32, 32}, // 9b45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b48 @@ -20918,13 +21219,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b53 - {0.683105f, 0.032227f, 0.699219f, 0.047852f, -1.2500f, -29.2500f, 30.0000f, 33, 32}, // 9b54 + {0.852539f, 0.048828f, 0.868652f, 0.064453f, -1.2500f, -29.2500f, 30.0000f, 33, 32}, // 9b54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b57 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b59 - {0.435059f, 0.163086f, 0.450684f, 0.178711f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 9b5a + {0.726074f, 0.187500f, 0.741699f, 0.203125f, -0.7500f, -29.5000f, 30.0000f, 32, 32}, // 9b5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b5b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9b5d @@ -21008,7 +21309,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bad - {0.685547f, 0.163086f, 0.701172f, 0.178711f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 9bae + {0.586426f, 0.187988f, 0.602051f, 0.203613f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 9bae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9baf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bb1 @@ -21066,7 +21367,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9be5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9be6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9be7 - {0.495605f, 0.164063f, 0.511230f, 0.179688f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 9be8 + {0.602539f, 0.187988f, 0.618164f, 0.203613f, -0.6875f, -29.3125f, 30.0000f, 32, 32}, // 9be8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9be9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9bea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9beb @@ -21319,7 +21620,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce4 - {0.687012f, 0.556641f, 0.701172f, 0.572266f, -0.0625f, -29.6250f, 30.0000f, 29, 32}, // 9ce5 + {0.491699f, 0.586426f, 0.505859f, 0.602051f, -0.0625f, -29.6250f, 30.0000f, 29, 32}, // 9ce5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ce8 @@ -21334,7 +21635,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf3 - {0.199707f, 0.557129f, 0.213867f, 0.572754f, 1.2500f, -29.5625f, 30.0000f, 29, 32}, // 9cf4 + {0.898438f, 0.586426f, 0.912598f, 0.602051f, 1.2500f, -29.5625f, 30.0000f, 29, 32}, // 9cf4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9cf7 @@ -21489,7 +21790,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d8e - {0.209473f, 0.164551f, 0.225098f, 0.180176f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 9d8f + {0.048340f, 0.188477f, 0.063965f, 0.204102f, -0.7500f, -29.2500f, 30.0000f, 32, 32}, // 9d8f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9d92 @@ -21637,7 +21938,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e20 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e21 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e22 - {0.459961f, 0.617188f, 0.474121f, 0.632324f, 0.9375f, -29.3125f, 30.0000f, 29, 31}, // 9e23 + {0.410156f, 0.646484f, 0.424316f, 0.661621f, 0.9375f, -29.3125f, 30.0000f, 29, 31}, // 9e23 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e24 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e25 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e26 @@ -21753,7 +22054,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e94 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e96 - {0.320801f, 0.350098f, 0.336426f, 0.365234f, -0.7500f, -28.4375f, 30.0000f, 32, 31}, // 9e97 + {0.475098f, 0.368164f, 0.490723f, 0.383301f, -0.7500f, -28.4375f, 30.0000f, 32, 31}, // 9e97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9e9a @@ -21768,7 +22069,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea5 - {0.670410f, 0.413086f, 0.685547f, 0.428223f, -0.3125f, -28.8125f, 30.0000f, 31, 31}, // 9ea6 + {0.332031f, 0.432617f, 0.347168f, 0.447754f, -0.3125f, -28.8125f, 30.0000f, 31, 31}, // 9ea6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ea9 @@ -21789,7 +22090,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9eb8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9eb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9eba - {0.225586f, 0.164551f, 0.241211f, 0.180176f, -0.7500f, -29.1875f, 30.0000f, 32, 32}, // 9ebb + {0.064453f, 0.188477f, 0.080078f, 0.204102f, -0.7500f, -29.1875f, 30.0000f, 32, 32}, // 9ebb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ebc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ebd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ebe @@ -21797,8 +22098,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec2 - {0.241699f, 0.164551f, 0.257324f, 0.180176f, -0.3750f, -28.8125f, 30.0000f, 32, 32}, // 9ec3 - {0.219238f, 0.463379f, 0.233887f, 0.479004f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 9ec4 + {0.080566f, 0.188477f, 0.096191f, 0.204102f, -0.3750f, -28.8125f, 30.0000f, 32, 32}, // 9ec3 + {0.172852f, 0.488281f, 0.187500f, 0.503906f, 0.2500f, -28.9375f, 30.0000f, 30, 32}, // 9ec4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ec7 @@ -21812,19 +22113,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ecf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed1 - {0.259277f, 0.596191f, 0.273926f, 0.610840f, 0.4375f, -27.6250f, 30.0000f, 30, 30}, // 9ed2 + {0.580566f, 0.622070f, 0.595215f, 0.636719f, 0.4375f, -27.6250f, 30.0000f, 30, 30}, // 9ed2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ed7 - {0.592285f, 0.350098f, 0.607910f, 0.365234f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 9ed8 - {0.639648f, 0.350098f, 0.655273f, 0.365234f, -0.7500f, -28.3125f, 30.0000f, 32, 31}, // 9ed9 + {0.287109f, 0.368652f, 0.302734f, 0.383789f, -0.6875f, -28.9375f, 30.0000f, 32, 31}, // 9ed8 + {0.817383f, 0.368652f, 0.833008f, 0.383789f, -0.7500f, -28.3125f, 30.0000f, 32, 31}, // 9ed9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9eda {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9edb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9edc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9edd - {0.096191f, 0.350098f, 0.111328f, 0.365723f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 9ede + {0.303223f, 0.368652f, 0.318359f, 0.384277f, -0.1250f, -29.1875f, 30.0000f, 31, 32}, // 9ede {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9edf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ee0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ee1 @@ -21877,7 +22178,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f12 - {0.257813f, 0.164551f, 0.273438f, 0.180176f, -0.2500f, -29.1250f, 30.0000f, 32, 32}, // 9f13 + {0.618652f, 0.188965f, 0.634277f, 0.204590f, -0.2500f, -29.1250f, 30.0000f, 32, 32}, // 9f13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f16 @@ -21917,7 +22218,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f3a - {0.354492f, 0.166016f, 0.370117f, 0.181641f, -0.7500f, -29.5625f, 30.0000f, 32, 32}, // 9f3b + {0.634766f, 0.188965f, 0.650391f, 0.204590f, -0.7500f, -29.5625f, 30.0000f, 32, 32}, // 9f3b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f3e @@ -21956,7 +22257,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f5f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f61 - {0.402832f, 0.168945f, 0.418457f, 0.184570f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 9f62 + {0.145020f, 0.189941f, 0.160645f, 0.205566f, -0.7500f, -29.3750f, 30.0000f, 32, 32}, // 9f62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f63 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f64 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f65 @@ -21985,7 +22286,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f7c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f7e - {0.848145f, 0.539551f, 0.862793f, 0.554688f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 9f7f + {0.736816f, 0.565918f, 0.751465f, 0.581055f, 0.2500f, -28.8750f, 30.0000f, 30, 31}, // 9f7f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9f82 @@ -22114,12 +22415,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ffd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9ffe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // 9fff -// RANGE: 0xac00 - 0xd7a4, start 0x5668 - {0.345703f, 0.467285f, 0.360352f, 0.482910f, 0.9375f, -29.3125f, 30.0000f, 30, 32}, // ac00 +// RANGE: 0xac00 - 0xd7a4, start 0x579c + {0.584961f, 0.488281f, 0.599609f, 0.503906f, 0.9375f, -29.3125f, 30.0000f, 30, 32}, // ac00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac03 - {0.932617f, 0.539551f, 0.947266f, 0.554688f, 0.6250f, -29.3125f, 30.0000f, 30, 31}, // ac04 + {0.245117f, 0.567383f, 0.259766f, 0.582520f, 0.6250f, -29.3125f, 30.0000f, 30, 31}, // ac04 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac07 @@ -22133,7 +22434,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac11 - {0.360840f, 0.467773f, 0.375488f, 0.483398f, 0.6250f, -29.1250f, 30.0000f, 30, 32}, // ac12 + {0.125977f, 0.489746f, 0.140625f, 0.505371f, 0.6250f, -29.1250f, 30.0000f, 30, 32}, // ac12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac13 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac15 @@ -22143,7 +22444,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac1b - {0.275391f, 0.557617f, 0.289551f, 0.573242f, 1.0625f, -29.3125f, 30.0000f, 29, 32}, // ac1c + {0.955566f, 0.586426f, 0.969727f, 0.602051f, 1.0625f, -29.3125f, 30.0000f, 29, 32}, // ac1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac1f @@ -22227,7 +22528,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac6f - {0.322266f, 0.560547f, 0.336426f, 0.576172f, 0.9375f, -29.2500f, 30.0000f, 29, 32}, // ac70 + {0.246582f, 0.587402f, 0.260742f, 0.603027f, 0.9375f, -29.2500f, 30.0000f, 29, 32}, // ac70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac73 @@ -22255,7 +22556,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac8b - {0.336914f, 0.560547f, 0.351074f, 0.576172f, 0.7500f, -29.3125f, 30.0000f, 29, 32}, // ac8c + {0.261230f, 0.587402f, 0.275391f, 0.603027f, 0.7500f, -29.3125f, 30.0000f, 29, 32}, // ac8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac8f @@ -22275,7 +22576,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac9d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac9e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ac9f - {0.108887f, 0.468262f, 0.123535f, 0.483887f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // aca0 + {0.266602f, 0.489746f, 0.281250f, 0.505371f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // aca0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // aca1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // aca2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // aca3 @@ -22291,7 +22592,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acaf - {0.351563f, 0.560547f, 0.365723f, 0.576172f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // acb0 + {0.785645f, 0.587402f, 0.799805f, 0.603027f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // acb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acb3 @@ -22304,14 +22605,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acbb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acbc - {0.000000f, 0.562012f, 0.014160f, 0.577637f, 0.6875f, -29.3125f, 30.0000f, 29, 32}, // acbd + {0.432129f, 0.587891f, 0.446289f, 0.603516f, 0.6875f, -29.3125f, 30.0000f, 29, 32}, // acbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acbf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc3 - {0.107422f, 0.562012f, 0.121582f, 0.577637f, 0.3125f, -29.3125f, 30.0000f, 29, 32}, // acc4 + {0.446777f, 0.587891f, 0.460938f, 0.603516f, 0.3125f, -29.3125f, 30.0000f, 29, 32}, // acc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acc7 @@ -22339,7 +22640,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acdd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acde {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acdf - {0.600098f, 0.693359f, 0.615234f, 0.705566f, -0.1250f, -25.0625f, 30.0000f, 31, 25}, // ace0 + {0.137207f, 0.735352f, 0.152344f, 0.747559f, -0.1250f, -25.0625f, 30.0000f, 31, 25}, // ace0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace3 @@ -22347,7 +22648,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace7 - {0.044922f, 0.648438f, 0.059570f, 0.662598f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // ace8 + {0.683594f, 0.680176f, 0.698242f, 0.694336f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // ace8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ace9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // acea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // aceb @@ -22451,7 +22752,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad4f - {0.629395f, 0.693359f, 0.644531f, 0.705566f, -0.1250f, -25.6875f, 30.0000f, 31, 25}, // ad50 + {0.617676f, 0.735840f, 0.632813f, 0.748047f, -0.1250f, -25.6875f, 30.0000f, 31, 25}, // ad50 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad53 @@ -22479,8 +22780,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad69 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad6a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad6b - {0.792969f, 0.596191f, 0.807617f, 0.610840f, 0.3750f, -27.4375f, 30.0000f, 30, 30}, // ad6c - {0.224609f, 0.648438f, 0.239258f, 0.662598f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // ad6d + {0.836914f, 0.622070f, 0.851563f, 0.636719f, 0.3750f, -27.4375f, 30.0000f, 30, 30}, // ad6c + {0.844727f, 0.680176f, 0.859375f, 0.694336f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // ad6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad6f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad70 @@ -22511,7 +22812,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad8b - {0.489258f, 0.617188f, 0.503418f, 0.632324f, 0.3750f, -29.2500f, 30.0000f, 29, 31}, // ad8c + {0.257324f, 0.646973f, 0.271484f, 0.662109f, 0.3750f, -29.2500f, 30.0000f, 29, 31}, // ad8c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ad8f @@ -22619,11 +22920,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adf7 - {0.592773f, 0.748047f, 0.607910f, 0.759277f, -0.3125f, -24.5625f, 30.0000f, 31, 23}, // adf8 + {0.227539f, 0.806152f, 0.242676f, 0.817383f, -0.3125f, -24.5625f, 30.0000f, 31, 23}, // adf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adfa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adfb - {0.605957f, 0.648438f, 0.620605f, 0.662598f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // adfc + {0.885254f, 0.681152f, 0.899902f, 0.695313f, 0.3125f, -27.1250f, 30.0000f, 30, 29}, // adfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // adff @@ -22675,7 +22976,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae2f - {0.014648f, 0.563965f, 0.028809f, 0.579590f, 0.6875f, -29.3125f, 30.0000f, 29, 32}, // ae30 + {0.937012f, 0.587891f, 0.951172f, 0.603516f, 0.6875f, -29.3125f, 30.0000f, 29, 32}, // ae30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae33 @@ -22683,7 +22984,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae37 - {0.000000f, 0.469238f, 0.014648f, 0.484863f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // ae38 + {0.234375f, 0.490723f, 0.249023f, 0.506348f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // ae38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae3b @@ -22696,14 +22997,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae43 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae44 - {0.015137f, 0.471191f, 0.029785f, 0.486816f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // ae45 + {0.725098f, 0.490723f, 0.739746f, 0.506348f, -0.1250f, -29.2500f, 30.0000f, 30, 32}, // ae45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae48 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae49 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae4a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae4b - {0.800781f, 0.350098f, 0.815918f, 0.365723f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // ae4c + {0.852539f, 0.369141f, 0.867676f, 0.384766f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // ae4c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae4d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae4e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ae4f @@ -23207,13 +23508,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b041 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b042 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b043 - {0.241211f, 0.708496f, 0.256348f, 0.720215f, -0.3125f, -24.7500f, 30.0000f, 31, 24}, // b044 + {0.287598f, 0.757813f, 0.302734f, 0.769531f, -0.3125f, -24.7500f, 30.0000f, 31, 24}, // b044 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b045 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b046 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b047 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b048 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b049 - {0.808105f, 0.596191f, 0.822754f, 0.610840f, 0.3125f, -27.0625f, 30.0000f, 30, 30}, // b04a + {0.922363f, 0.622070f, 0.937012f, 0.636719f, 0.3125f, -27.0625f, 30.0000f, 30, 30}, // b04a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b04b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b04c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b04d @@ -23291,7 +23592,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b095 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b096 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b097 - {0.260254f, 0.564941f, 0.274414f, 0.580566f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b098 + {0.372070f, 0.588379f, 0.386230f, 0.604004f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b098 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b099 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b09a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b09b @@ -23299,7 +23600,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b09d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b09e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b09f - {0.801270f, 0.564941f, 0.815430f, 0.580566f, 1.2500f, -29.2500f, 30.0000f, 29, 32}, // b0a0 + {0.800293f, 0.588379f, 0.814453f, 0.604004f, 1.2500f, -29.2500f, 30.0000f, 29, 32}, // b0a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b0a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b0a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b0a3 @@ -23431,7 +23732,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b121 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b122 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b123 - {0.334961f, 0.622559f, 0.348633f, 0.638184f, 2.0000f, -29.3125f, 30.0000f, 28, 32}, // b124 + {0.243164f, 0.652832f, 0.256836f, 0.668457f, 2.0000f, -29.3125f, 30.0000f, 28, 32}, // b124 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b125 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b126 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b127 @@ -23450,7 +23751,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b134 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b135 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b136 - {0.815918f, 0.564941f, 0.830078f, 0.580566f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b137 + {0.877930f, 0.588379f, 0.892090f, 0.604004f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b137 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b138 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b139 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b13a @@ -23655,7 +23956,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b201 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b202 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b203 - {0.030273f, 0.596680f, 0.044922f, 0.611328f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // b204 + {0.781738f, 0.622559f, 0.796387f, 0.637207f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // b204 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b205 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b206 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b207 @@ -23767,7 +24068,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b271 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b272 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b273 - {0.045410f, 0.596680f, 0.060059f, 0.611328f, 0.1250f, -27.9375f, 30.0000f, 30, 30}, // b274 + {0.852051f, 0.622559f, 0.866699f, 0.637207f, 0.1250f, -27.9375f, 30.0000f, 30, 30}, // b274 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b275 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b276 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b277 @@ -23799,11 +24100,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b291 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b292 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b293 - {0.151855f, 0.596680f, 0.166504f, 0.611328f, 0.3125f, -28.3750f, 30.0000f, 30, 30}, // b294 + {0.320313f, 0.623047f, 0.334961f, 0.637695f, 0.3125f, -28.3750f, 30.0000f, 30, 30}, // b294 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b295 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b296 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b297 - {0.015137f, 0.598145f, 0.029785f, 0.612793f, 0.3125f, -28.0625f, 30.0000f, 30, 30}, // b298 + {0.272949f, 0.623535f, 0.287598f, 0.638184f, 0.3125f, -28.0625f, 30.0000f, 30, 30}, // b298 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b299 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b29a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b29b @@ -23816,7 +24117,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a4 - {0.947754f, 0.539551f, 0.962402f, 0.554688f, 0.3125f, -28.0625f, 30.0000f, 30, 31}, // b2a5 + {0.229980f, 0.567871f, 0.244629f, 0.583008f, 0.3125f, -28.0625f, 30.0000f, 30, 31}, // b2a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2a8 @@ -23851,8 +24152,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2c7 - {0.091309f, 0.624023f, 0.104980f, 0.639648f, 2.1250f, -29.3125f, 30.0000f, 28, 32}, // b2c8 - {0.105469f, 0.624023f, 0.119141f, 0.639648f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b2c9 + {0.317871f, 0.652832f, 0.331543f, 0.668457f, 2.1250f, -29.3125f, 30.0000f, 28, 32}, // b2c8 + {0.424805f, 0.652832f, 0.438477f, 0.668457f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b2c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2cc @@ -23879,7 +24180,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e3 - {0.045410f, 0.565430f, 0.059570f, 0.581055f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b2e4 + {0.307617f, 0.589844f, 0.321777f, 0.605469f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // b2e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2e7 @@ -23900,14 +24201,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2f8 - {0.060059f, 0.565430f, 0.074219f, 0.581055f, 1.2500f, -29.1250f, 30.0000f, 29, 32}, // b2f9 + {0.352539f, 0.589844f, 0.366699f, 0.605469f, 1.2500f, -29.1250f, 30.0000f, 29, 32}, // b2f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b2ff - {0.791016f, 0.625977f, 0.804688f, 0.641602f, 1.2500f, -29.3125f, 30.0000f, 28, 32}, // b300 + {0.438965f, 0.652832f, 0.452637f, 0.668457f, 1.2500f, -29.3125f, 30.0000f, 28, 32}, // b300 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b301 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b302 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b303 @@ -23991,7 +24292,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b351 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b352 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b353 - {0.149414f, 0.626465f, 0.163086f, 0.642090f, 1.2500f, -29.2500f, 30.0000f, 28, 32}, // b354 + {0.576172f, 0.652832f, 0.589844f, 0.668457f, 1.2500f, -29.2500f, 30.0000f, 28, 32}, // b354 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b355 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b356 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b357 @@ -24007,7 +24308,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b361 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b362 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b363 - {0.257813f, 0.626953f, 0.271484f, 0.642578f, 1.2500f, -29.2500f, 30.0000f, 28, 32}, // b364 + {0.920410f, 0.652832f, 0.934082f, 0.668457f, 1.2500f, -29.2500f, 30.0000f, 28, 32}, // b364 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b365 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b366 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b367 @@ -24017,9 +24318,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b36b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b36c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b36d - {0.152832f, 0.565430f, 0.166992f, 0.581055f, 1.2500f, -29.2500f, 30.0000f, 29, 32}, // b36e + {0.831543f, 0.589844f, 0.845703f, 0.605469f, 1.2500f, -29.2500f, 30.0000f, 29, 32}, // b36e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b36f - {0.805176f, 0.626953f, 0.818848f, 0.642578f, 1.2500f, -29.3125f, 30.0000f, 28, 32}, // b370 + {0.773438f, 0.653320f, 0.787109f, 0.668945f, 1.2500f, -29.3125f, 30.0000f, 28, 32}, // b370 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b371 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b372 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b373 @@ -24103,7 +24404,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c3 - {0.301270f, 0.649414f, 0.316406f, 0.663086f, -0.1250f, -26.8125f, 30.0000f, 31, 28}, // b3c4 + {0.984375f, 0.683594f, 0.999512f, 0.697266f, -0.1250f, -26.8125f, 30.0000f, 31, 28}, // b3c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c7 @@ -24111,7 +24412,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3cb - {0.525879f, 0.598145f, 0.540527f, 0.612793f, 0.3125f, -27.6875f, 30.0000f, 30, 30}, // b3cc + {0.288086f, 0.624023f, 0.302734f, 0.638672f, 0.3125f, -27.6875f, 30.0000f, 30, 30}, // b3cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3cf @@ -24124,7 +24425,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3d7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3d8 - {0.746094f, 0.598145f, 0.760742f, 0.612793f, 0.3125f, -27.6875f, 30.0000f, 30, 30}, // b3d9 + {0.615234f, 0.624023f, 0.629883f, 0.638672f, 0.3125f, -27.6875f, 30.0000f, 30, 30}, // b3d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b3dc @@ -24187,11 +24488,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b415 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b416 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b417 - {0.047363f, 0.471191f, 0.062012f, 0.486816f, -0.1875f, -29.3125f, 30.0000f, 30, 32}, // b418 + {0.016113f, 0.491211f, 0.030762f, 0.506836f, -0.1875f, -29.3125f, 30.0000f, 30, 32}, // b418 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b419 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b41a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b41b - {0.962891f, 0.539551f, 0.977539f, 0.554688f, -0.1250f, -29.2500f, 30.0000f, 30, 31}, // b41c + {0.400391f, 0.568848f, 0.415039f, 0.583984f, -0.1250f, -29.2500f, 30.0000f, 30, 31}, // b41c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b41d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b41e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b41f @@ -24203,8 +24504,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b425 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b426 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b427 - {0.281250f, 0.472168f, 0.295898f, 0.487793f, -0.1250f, -29.3125f, 30.0000f, 30, 32}, // b428 - {0.828125f, 0.472168f, 0.842773f, 0.487793f, -0.1250f, -29.3125f, 30.0000f, 30, 32}, // b429 + {0.218262f, 0.491211f, 0.232910f, 0.506836f, -0.1250f, -29.3125f, 30.0000f, 30, 32}, // b428 + {0.409668f, 0.491211f, 0.424316f, 0.506836f, -0.1250f, -29.3125f, 30.0000f, 30, 32}, // b429 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b42a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b42b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b42c @@ -24243,7 +24544,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b44d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b44e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b44f - {0.665039f, 0.598633f, 0.679688f, 0.613281f, 0.3750f, -27.6875f, 30.0000f, 30, 30}, // b450 + {0.762207f, 0.624023f, 0.776855f, 0.638672f, 0.3750f, -27.6875f, 30.0000f, 30, 30}, // b450 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b451 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b452 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b453 @@ -24251,7 +24552,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b455 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b456 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b457 - {0.696289f, 0.598633f, 0.710938f, 0.613281f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b458 + {0.089844f, 0.625000f, 0.104492f, 0.639648f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b458 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b459 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b45a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b45b @@ -24327,7 +24628,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a3 - {0.062500f, 0.472656f, 0.077148f, 0.488281f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // b4a4 + {0.424805f, 0.491211f, 0.439453f, 0.506836f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // b4a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4a7 @@ -24383,15 +24684,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4db - {0.380371f, 0.708496f, 0.395508f, 0.720215f, -0.3125f, -25.2500f, 30.0000f, 31, 24}, // b4dc + {0.526367f, 0.757813f, 0.541504f, 0.769531f, -0.3125f, -25.2500f, 30.0000f, 31, 24}, // b4dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4df - {0.862793f, 0.648438f, 0.877441f, 0.662598f, 0.3125f, -27.5625f, 30.0000f, 30, 29}, // b4e0 + {0.955078f, 0.681152f, 0.969727f, 0.695313f, 0.3125f, -27.5625f, 30.0000f, 30, 29}, // b4e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e3 - {0.166992f, 0.599121f, 0.181641f, 0.613770f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b4e4 + {0.104980f, 0.625000f, 0.119629f, 0.639648f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b4e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4e7 @@ -24404,7 +24705,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4f0 - {0.474609f, 0.599121f, 0.489258f, 0.613770f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b4f1 + {0.335449f, 0.625488f, 0.350098f, 0.640137f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // b4f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b4f4 @@ -24439,8 +24740,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b511 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b512 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b513 - {0.034180f, 0.627441f, 0.047852f, 0.643066f, 1.5625f, -29.3125f, 30.0000f, 28, 32}, // b514 - {0.520508f, 0.627930f, 0.534180f, 0.643555f, 1.6875f, -29.2500f, 30.0000f, 28, 32}, // b515 + {0.271973f, 0.653809f, 0.285645f, 0.669434f, 1.5625f, -29.3125f, 30.0000f, 28, 32}, // b514 + {0.286133f, 0.654785f, 0.299805f, 0.670410f, 1.6875f, -29.2500f, 30.0000f, 28, 32}, // b515 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b516 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b517 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b518 @@ -24460,14 +24761,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b526 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b527 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b528 - {0.631836f, 0.628906f, 0.645508f, 0.644531f, 1.6875f, -29.2500f, 30.0000f, 28, 32}, // b529 + {0.611328f, 0.654785f, 0.625000f, 0.670410f, 1.6875f, -29.2500f, 30.0000f, 28, 32}, // b529 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b52f - {0.030273f, 0.473145f, 0.044922f, 0.488770f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // b530 + {0.698730f, 0.491211f, 0.713379f, 0.506836f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // b530 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b531 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b532 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b533 @@ -25083,7 +25384,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b795 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b796 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b797 - {0.742676f, 0.628906f, 0.756348f, 0.644531f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b798 + {0.758301f, 0.654785f, 0.771973f, 0.670410f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b798 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b799 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b79a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b79b @@ -25102,7 +25403,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7aa - {0.029297f, 0.566895f, 0.043457f, 0.582520f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7ab + {0.668945f, 0.590332f, 0.683105f, 0.605957f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ae @@ -25167,8 +25468,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7eb - {0.883789f, 0.628906f, 0.897461f, 0.644531f, 1.5000f, -29.2500f, 30.0000f, 28, 32}, // b7ec - {0.530273f, 0.566895f, 0.544434f, 0.582520f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7ed + {0.089844f, 0.655762f, 0.103516f, 0.671387f, 1.5000f, -29.2500f, 30.0000f, 28, 32}, // b7ec + {0.970215f, 0.590332f, 0.984375f, 0.605957f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7f0 @@ -25183,7 +25484,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7fb - {0.748535f, 0.566895f, 0.762695f, 0.582520f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7fc + {0.984863f, 0.590332f, 0.999023f, 0.605957f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b7fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b7ff @@ -25195,11 +25496,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b805 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b806 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b807 - {0.897949f, 0.628906f, 0.911621f, 0.644531f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b808 - {0.664063f, 0.629395f, 0.677734f, 0.645020f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b809 + {0.104004f, 0.655762f, 0.117676f, 0.671387f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b808 + {0.196289f, 0.655762f, 0.209961f, 0.671387f, 1.5000f, -29.3125f, 30.0000f, 28, 32}, // b809 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b80a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b80b - {0.000000f, 0.649902f, 0.013672f, 0.665039f, 1.5000f, -29.3125f, 30.0000f, 28, 31}, // b80c + {0.314941f, 0.684082f, 0.328613f, 0.699219f, 1.5000f, -29.3125f, 30.0000f, 28, 31}, // b80c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b80d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b80e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b80f @@ -25223,8 +25524,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b821 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b822 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b823 - {0.692871f, 0.629395f, 0.706543f, 0.645020f, 1.5000f, -29.2500f, 30.0000f, 28, 32}, // b824 - {0.668945f, 0.567383f, 0.683105f, 0.583008f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b825 + {0.059570f, 0.656250f, 0.073242f, 0.671875f, 1.5000f, -29.2500f, 30.0000f, 28, 32}, // b824 + {0.590332f, 0.590820f, 0.604492f, 0.606445f, 1.0625f, -29.2500f, 30.0000f, 29, 32}, // b825 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b826 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b827 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b828 @@ -25279,15 +25580,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b859 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b85a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b85b - {0.263672f, 0.682129f, 0.278809f, 0.694824f, -0.1250f, -26.6875f, 30.0000f, 31, 26}, // b85c - {0.541016f, 0.599121f, 0.555664f, 0.613770f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b85d + {0.218262f, 0.721191f, 0.233398f, 0.733887f, -0.1250f, -26.6875f, 30.0000f, 31, 26}, // b85c + {0.630371f, 0.625488f, 0.645020f, 0.640137f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b85d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b85e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b85f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b860 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b861 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b862 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b863 - {0.556152f, 0.599121f, 0.570801f, 0.613770f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b864 + {0.743652f, 0.625488f, 0.758301f, 0.640137f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b864 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b865 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b866 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b867 @@ -25391,7 +25692,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8cb - {0.310059f, 0.682617f, 0.325195f, 0.695313f, -0.1250f, -26.6875f, 30.0000f, 31, 26}, // b8cc + {0.688477f, 0.721191f, 0.703613f, 0.733887f, -0.1250f, -26.6875f, 30.0000f, 31, 26}, // b8cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8cf @@ -25419,7 +25720,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8e7 - {0.571289f, 0.599121f, 0.585938f, 0.613770f, 0.3750f, -27.8750f, 30.0000f, 30, 30}, // b8e8 + {0.197266f, 0.625977f, 0.211914f, 0.640625f, 0.3750f, -27.8750f, 30.0000f, 30, 30}, // b8e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b8eb @@ -25531,7 +25832,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b955 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b956 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b957 - {0.633789f, 0.599121f, 0.648438f, 0.613770f, 0.1250f, -27.8750f, 30.0000f, 30, 30}, // b958 + {0.059570f, 0.626465f, 0.074219f, 0.641113f, 0.1250f, -27.8750f, 30.0000f, 30, 30}, // b958 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b959 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b95a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b95b @@ -25547,7 +25848,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b965 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b966 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b967 - {0.889648f, 0.599121f, 0.904297f, 0.613770f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b968 + {0.455566f, 0.626465f, 0.470215f, 0.641113f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b968 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b969 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b96a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b96b @@ -25559,15 +25860,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b971 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b972 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b973 - {0.855469f, 0.693359f, 0.870605f, 0.705566f, -0.3125f, -25.9375f, 30.0000f, 31, 25}, // b974 + {0.717285f, 0.735840f, 0.732422f, 0.748047f, -0.3125f, -25.9375f, 30.0000f, 31, 25}, // b974 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b975 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b976 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b977 - {0.904785f, 0.599121f, 0.919434f, 0.613770f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b978 + {0.645508f, 0.626465f, 0.660156f, 0.641113f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b978 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b979 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b97a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b97b - {0.305176f, 0.600098f, 0.319824f, 0.614746f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b97c + {0.044434f, 0.626953f, 0.059082f, 0.641602f, 0.3125f, -27.8750f, 30.0000f, 30, 30}, // b97c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b97d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b97e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b97f @@ -25615,15 +25916,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ab - {0.147949f, 0.657227f, 0.161133f, 0.672852f, 2.2500f, -29.3125f, 30.0000f, 27, 32}, // b9ac + {0.449707f, 0.687500f, 0.462891f, 0.703125f, 2.2500f, -29.3125f, 30.0000f, 27, 32}, // b9ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9af - {0.674805f, 0.650391f, 0.688477f, 0.665527f, 2.1250f, -29.3125f, 30.0000f, 28, 31}, // b9b0 + {0.770508f, 0.684570f, 0.784180f, 0.699707f, 2.1250f, -29.3125f, 30.0000f, 28, 31}, // b9b0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b3 - {0.163574f, 0.629883f, 0.177246f, 0.645508f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9b4 + {0.332031f, 0.656250f, 0.345703f, 0.671875f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9b7 @@ -25632,11 +25933,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9bc - {0.399414f, 0.629883f, 0.413086f, 0.645508f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9bd + {0.453125f, 0.656250f, 0.466797f, 0.671875f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9c0 - {0.474609f, 0.629883f, 0.488281f, 0.645508f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9c1 + {0.625488f, 0.656250f, 0.639160f, 0.671875f, 2.1250f, -29.2500f, 30.0000f, 28, 32}, // b9c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9c4 @@ -25647,12 +25948,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9cb - {0.583496f, 0.617188f, 0.597656f, 0.632324f, 1.6250f, -29.3125f, 30.0000f, 29, 31}, // b9cc + {0.675293f, 0.646973f, 0.689453f, 0.662109f, 1.6250f, -29.3125f, 30.0000f, 29, 31}, // b9cc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9cf - {0.701660f, 0.567383f, 0.715820f, 0.583008f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9d0 - {0.167480f, 0.567871f, 0.181641f, 0.583496f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9d1 + {0.846191f, 0.590820f, 0.860352f, 0.606445f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9d0 + {0.860840f, 0.591309f, 0.875000f, 0.606934f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9d3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9d4 @@ -25665,13 +25966,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9dd - {0.481445f, 0.567871f, 0.495605f, 0.583496f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9de + {0.322266f, 0.591797f, 0.336426f, 0.607422f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e3 - {0.503906f, 0.629883f, 0.517578f, 0.645508f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // b9e4 + {0.741211f, 0.656250f, 0.754883f, 0.671875f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // b9e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9e7 @@ -25688,9 +25989,9 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f4 - {0.534668f, 0.629883f, 0.548340f, 0.645508f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // b9f5 + {0.118164f, 0.656738f, 0.131836f, 0.672363f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // b9f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f6 - {0.544922f, 0.567871f, 0.559082f, 0.583496f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9f7 + {0.275879f, 0.592285f, 0.290039f, 0.607910f, 1.6250f, -29.2500f, 30.0000f, 29, 32}, // b9f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // b9fa @@ -25755,15 +26056,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba37 - {0.548828f, 0.629883f, 0.562500f, 0.645508f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // ba38 + {0.500977f, 0.656738f, 0.514648f, 0.672363f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // ba38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba3b - {0.910645f, 0.650391f, 0.924316f, 0.665527f, 1.3125f, -29.2500f, 30.0000f, 28, 31}, // ba3c + {0.270508f, 0.685059f, 0.284180f, 0.700195f, 1.3125f, -29.2500f, 30.0000f, 28, 31}, // ba3c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba3d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba3e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba3f - {0.562988f, 0.629883f, 0.576660f, 0.645508f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // ba40 + {0.179688f, 0.657227f, 0.193359f, 0.672852f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // ba40 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba43 @@ -25783,7 +26084,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba53 - {0.725098f, 0.630371f, 0.738770f, 0.645996f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // ba54 + {0.639648f, 0.657227f, 0.653320f, 0.672852f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // ba54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba57 @@ -25811,11 +26112,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba6d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba6e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba6f - {0.074219f, 0.630859f, 0.087891f, 0.646484f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // ba70 + {0.044922f, 0.657715f, 0.058594f, 0.673340f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // ba70 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba73 - {0.177734f, 0.650879f, 0.191406f, 0.666016f, 1.3125f, -29.3125f, 30.0000f, 28, 31}, // ba74 + {0.604980f, 0.685547f, 0.618652f, 0.700684f, 1.3125f, -29.3125f, 30.0000f, 28, 31}, // ba74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba77 @@ -25832,7 +26133,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba83 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba84 - {0.212402f, 0.630859f, 0.226074f, 0.646484f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // ba85 + {0.073730f, 0.657715f, 0.087402f, 0.673340f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // ba85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba87 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ba88 @@ -25867,8 +26168,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baa5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baa6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baa7 - {0.325684f, 0.683105f, 0.340820f, 0.695801f, -0.1250f, -26.2500f, 30.0000f, 31, 26}, // baa8 - {0.414063f, 0.600098f, 0.428711f, 0.614746f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // baa9 + {0.171875f, 0.721680f, 0.187012f, 0.734375f, -0.1250f, -26.2500f, 30.0000f, 31, 26}, // baa8 + {0.074707f, 0.626953f, 0.089355f, 0.641602f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // baa9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baaa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // baac @@ -26007,11 +26308,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb33 - {0.508789f, 0.600098f, 0.523438f, 0.614746f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bb34 + {0.120117f, 0.626953f, 0.134766f, 0.641602f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bb34 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb35 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb36 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb37 - {0.777344f, 0.600098f, 0.791992f, 0.614746f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bb38 + {0.501465f, 0.626953f, 0.516113f, 0.641602f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bb38 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb39 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb3a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bb3b @@ -26127,7 +26428,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bba9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbaa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbab - {0.823242f, 0.600098f, 0.837891f, 0.614746f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bbac + {0.550781f, 0.626953f, 0.565430f, 0.641602f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // bbac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbaf @@ -26203,7 +26504,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbf7 - {0.028809f, 0.658203f, 0.041992f, 0.673828f, 2.3750f, -29.3125f, 30.0000f, 27, 32}, // bbf8 + {0.619141f, 0.687500f, 0.632324f, 0.703125f, 2.3750f, -29.3125f, 30.0000f, 27, 32}, // bbf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbfa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bbfb @@ -26220,26 +26521,26 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc07 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc08 - {0.254883f, 0.658203f, 0.268066f, 0.673828f, 2.6875f, -29.2500f, 30.0000f, 27, 32}, // bc09 + {0.116211f, 0.687988f, 0.129395f, 0.703613f, 2.6875f, -29.2500f, 30.0000f, 27, 32}, // bc09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc0e - {0.286133f, 0.630859f, 0.299805f, 0.646484f, 2.6875f, -29.2500f, 30.0000f, 28, 32}, // bc0f + {0.467285f, 0.657715f, 0.480957f, 0.673340f, 2.6875f, -29.2500f, 30.0000f, 28, 32}, // bc0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc10 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc13 - {0.559570f, 0.567871f, 0.573730f, 0.583496f, 1.6250f, -29.3125f, 30.0000f, 29, 32}, // bc14 + {0.106445f, 0.592773f, 0.120605f, 0.608398f, 1.6250f, -29.3125f, 30.0000f, 29, 32}, // bc14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc17 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc18 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc1a - {0.918457f, 0.617188f, 0.932617f, 0.632324f, 1.6250f, -29.1250f, 30.0000f, 29, 31}, // bc1b - {0.933105f, 0.617188f, 0.947266f, 0.632324f, 1.6250f, -29.1250f, 30.0000f, 29, 31}, // bc1c + {0.689941f, 0.646973f, 0.704102f, 0.662109f, 1.6250f, -29.1250f, 30.0000f, 29, 31}, // bc1b + {0.000000f, 0.647461f, 0.014160f, 0.662598f, 1.6250f, -29.1250f, 30.0000f, 29, 31}, // bc1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc1f @@ -26252,14 +26553,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc26 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc27 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc28 - {0.574219f, 0.567871f, 0.588379f, 0.583496f, 1.6250f, -29.1250f, 30.0000f, 29, 32}, // bc29 + {0.290527f, 0.592773f, 0.304688f, 0.608398f, 1.6250f, -29.1250f, 30.0000f, 29, 32}, // bc29 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc2f - {0.300293f, 0.630859f, 0.313965f, 0.646484f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // bc30 + {0.515137f, 0.657715f, 0.528809f, 0.673340f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // bc30 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc31 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc32 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc33 @@ -26343,11 +26644,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc83 - {0.598145f, 0.630859f, 0.611816f, 0.646484f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // bc84 + {0.547363f, 0.657715f, 0.561035f, 0.673340f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // bc84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc87 - {0.270996f, 0.650879f, 0.284668f, 0.666016f, 1.6250f, -29.2500f, 30.0000f, 28, 31}, // bc88 + {0.748535f, 0.685547f, 0.762207f, 0.700684f, 1.6250f, -29.2500f, 30.0000f, 28, 31}, // bc88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc8b @@ -26360,7 +26661,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc94 - {0.772949f, 0.630859f, 0.786621f, 0.646484f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // bc95 + {0.590332f, 0.657715f, 0.604004f, 0.673340f, 1.6250f, -29.2500f, 30.0000f, 28, 32}, // bc95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bc98 @@ -26379,7 +26680,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bca5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bca6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bca7 - {0.819336f, 0.630859f, 0.833008f, 0.646484f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // bca8 + {0.132324f, 0.658203f, 0.145996f, 0.673828f, 1.8125f, -29.3125f, 30.0000f, 28, 32}, // bca8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bca9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcaa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcab @@ -26399,15 +26700,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcb9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcbb - {0.981445f, 0.630859f, 0.995117f, 0.646484f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // bcbc + {0.030273f, 0.658691f, 0.043945f, 0.674316f, 1.8125f, -29.2500f, 30.0000f, 28, 32}, // bcbc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcbd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcbe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcbf - {0.316895f, 0.653320f, 0.330566f, 0.668457f, 1.6250f, -29.3125f, 30.0000f, 28, 31}, // bcc0 + {0.284668f, 0.686035f, 0.298340f, 0.701172f, 1.6250f, -29.3125f, 30.0000f, 28, 31}, // bcc0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc3 - {0.195801f, 0.631348f, 0.209473f, 0.646973f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // bcc4 + {0.146484f, 0.658691f, 0.160156f, 0.674316f, 1.6250f, -29.3125f, 30.0000f, 28, 32}, // bcc4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcc7 @@ -26455,15 +26756,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf3 - {0.103027f, 0.654785f, 0.118164f, 0.668457f, -0.1250f, -27.8750f, 30.0000f, 31, 28}, // bcf4 + {0.192383f, 0.686523f, 0.207520f, 0.700195f, -0.1250f, -27.8750f, 30.0000f, 31, 28}, // bcf4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf7 - {0.395996f, 0.600586f, 0.410645f, 0.615234f, 0.3125f, -28.5000f, 30.0000f, 30, 30}, // bcf8 + {0.180664f, 0.627441f, 0.195313f, 0.642090f, 0.3125f, -28.5000f, 30.0000f, 30, 30}, // bcf8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcf9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcfa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcfb - {0.978027f, 0.539551f, 0.992676f, 0.554688f, 0.3125f, -28.5000f, 30.0000f, 30, 31}, // bcfc + {0.576660f, 0.568848f, 0.591309f, 0.583984f, 0.3125f, -28.5000f, 30.0000f, 30, 31}, // bcfc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcfd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcfe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bcff @@ -26595,15 +26896,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd7d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd7e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd7f - {0.451660f, 0.540039f, 0.466309f, 0.555176f, 0.3750f, -28.5000f, 30.0000f, 30, 31}, // bd80 + {0.707031f, 0.568848f, 0.721680f, 0.583984f, 0.3750f, -28.5000f, 30.0000f, 30, 31}, // bd80 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd81 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd82 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd83 - {0.728516f, 0.600586f, 0.743164f, 0.615234f, 0.3125f, -28.5000f, 30.0000f, 30, 30}, // bd84 + {0.029785f, 0.627930f, 0.044434f, 0.642578f, 0.3125f, -28.5000f, 30.0000f, 30, 30}, // bd84 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd85 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd86 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd87 - {0.884277f, 0.540039f, 0.898926f, 0.555176f, 0.3125f, -28.5000f, 30.0000f, 30, 31}, // bd88 + {0.415527f, 0.569336f, 0.430176f, 0.584473f, 0.3125f, -28.5000f, 30.0000f, 30, 31}, // bd88 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd89 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd8a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bd8b @@ -26707,7 +27008,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bded {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bdee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bdef - {0.917480f, 0.540039f, 0.932129f, 0.555176f, 0.1250f, -28.5000f, 30.0000f, 30, 31}, // bdf0 + {0.430664f, 0.569336f, 0.445313f, 0.584473f, 0.1250f, -28.5000f, 30.0000f, 30, 31}, // bdf0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bdf1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bdf2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // bdf3 @@ -26735,7 +27036,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be0b - {0.070801f, 0.684570f, 0.085938f, 0.697266f, -0.3125f, -26.5000f, 30.0000f, 31, 26}, // be0c + {0.355957f, 0.721680f, 0.371094f, 0.734375f, -0.3125f, -26.5000f, 30.0000f, 31, 26}, // be0c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be0f @@ -26743,7 +27044,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be11 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be12 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be13 - {0.245117f, 0.540527f, 0.259766f, 0.555664f, 0.3125f, -28.8125f, 30.0000f, 30, 31}, // be14 + {0.687988f, 0.569336f, 0.702637f, 0.584473f, 0.3125f, -28.8125f, 30.0000f, 30, 31}, // be14 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be15 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be16 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be17 @@ -26791,8 +27092,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be41 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be42 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be43 - {0.801758f, 0.658203f, 0.814941f, 0.673828f, 2.3750f, -29.3125f, 30.0000f, 27, 32}, // be44 - {0.517578f, 0.658691f, 0.530762f, 0.674316f, 2.6875f, -29.2500f, 30.0000f, 27, 32}, // be45 + {0.481934f, 0.687988f, 0.495117f, 0.703613f, 2.3750f, -29.3125f, 30.0000f, 27, 32}, // be44 + {0.495605f, 0.687988f, 0.508789f, 0.703613f, 2.6875f, -29.2500f, 30.0000f, 27, 32}, // be45 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be46 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be47 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be48 @@ -26819,7 +27120,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be5f - {0.154297f, 0.473145f, 0.168945f, 0.488770f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // be60 + {0.740234f, 0.491211f, 0.754883f, 0.506836f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // be60 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be61 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be62 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // be63 @@ -27407,8 +27708,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0ab - {0.864746f, 0.350098f, 0.879883f, 0.365723f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // c0ac - {0.535645f, 0.473145f, 0.550293f, 0.488770f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0ad + {0.523926f, 0.369629f, 0.539063f, 0.385254f, -0.6250f, -29.3125f, 30.0000f, 31, 32}, // c0ac + {0.439941f, 0.492188f, 0.454590f, 0.507813f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0af {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0b0 @@ -27428,15 +27729,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0bf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c0 - {0.679688f, 0.473633f, 0.694336f, 0.489258f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0c1 + {0.501465f, 0.493164f, 0.516113f, 0.508789f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0c7 - {0.712402f, 0.473633f, 0.727051f, 0.489258f, -0.7500f, -29.3125f, 30.0000f, 30, 32}, // c0c8 - {0.636719f, 0.567871f, 0.650879f, 0.583496f, 0.1875f, -29.2500f, 30.0000f, 29, 32}, // c0c9 + {0.802734f, 0.493164f, 0.817383f, 0.508789f, -0.7500f, -29.3125f, 30.0000f, 30, 32}, // c0c8 + {0.621582f, 0.592773f, 0.635742f, 0.608398f, 0.1875f, -29.2500f, 30.0000f, 29, 32}, // c0c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0cb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0cc @@ -27456,7 +27757,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0db {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0dc - {0.169434f, 0.474121f, 0.184082f, 0.489746f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // c0dd + {0.841797f, 0.493164f, 0.856445f, 0.508789f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // c0dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0e0 @@ -27482,7 +27783,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0f6 - {0.550781f, 0.474609f, 0.565430f, 0.490234f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0f7 + {0.923828f, 0.493652f, 0.938477f, 0.509277f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c0f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0f8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c0fa @@ -27519,15 +27820,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c119 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c11a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c11b - {0.565918f, 0.474609f, 0.580566f, 0.490234f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // c11c + {0.938965f, 0.493652f, 0.953613f, 0.509277f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // c11c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c11d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c11e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c11f - {0.369629f, 0.540527f, 0.384277f, 0.555664f, -0.1875f, -29.2500f, 30.0000f, 30, 31}, // c120 + {0.000000f, 0.569824f, 0.014648f, 0.584961f, -0.1875f, -29.2500f, 30.0000f, 30, 31}, // c120 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c121 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c122 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c123 - {0.761719f, 0.474609f, 0.776367f, 0.490234f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c124 + {0.972168f, 0.493652f, 0.986816f, 0.509277f, 0.3750f, -29.2500f, 30.0000f, 30, 32}, // c124 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c125 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c126 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c127 @@ -27540,18 +27841,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c12e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c12f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c130 - {0.893066f, 0.567871f, 0.907227f, 0.583496f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c131 + {0.766602f, 0.592773f, 0.780762f, 0.608398f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c131 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c132 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c133 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c134 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c135 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c136 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c137 - {0.487793f, 0.475098f, 0.502441f, 0.490723f, -0.6250f, -29.3125f, 30.0000f, 30, 32}, // c138 + {0.281738f, 0.494629f, 0.296387f, 0.510254f, -0.6250f, -29.3125f, 30.0000f, 30, 32}, // c138 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c139 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c13a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c13b - {0.434082f, 0.540527f, 0.448730f, 0.555664f, -0.3125f, -29.3125f, 30.0000f, 30, 31}, // c13c + {0.168457f, 0.569824f, 0.183105f, 0.584961f, -0.3125f, -29.3125f, 30.0000f, 30, 31}, // c13c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c13d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c13e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c13f @@ -27563,10 +27864,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c145 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c146 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c147 - {0.306152f, 0.568848f, 0.320313f, 0.584473f, 0.2500f, -29.3125f, 30.0000f, 29, 32}, // c148 + {0.092285f, 0.593750f, 0.106445f, 0.609375f, 0.2500f, -29.3125f, 30.0000f, 29, 32}, // c148 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c149 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c14a - {0.581055f, 0.475098f, 0.595703f, 0.490723f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // c14b + {0.455078f, 0.494629f, 0.469727f, 0.510254f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // c14b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c14c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c14d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c14e @@ -27579,7 +27880,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c155 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c156 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c157 - {0.863281f, 0.540527f, 0.877930f, 0.555664f, -0.3125f, -29.2500f, 30.0000f, 30, 31}, // c158 + {0.215332f, 0.569824f, 0.229980f, 0.584961f, -0.3125f, -29.2500f, 30.0000f, 30, 31}, // c158 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c159 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c15a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c15b @@ -27631,15 +27932,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c189 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c18a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c18b - {0.313965f, 0.668945f, 0.329102f, 0.682129f, -0.1250f, -27.1250f, 30.0000f, 31, 27}, // c18c - {0.687500f, 0.541016f, 0.702148f, 0.556152f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c18d + {0.048340f, 0.062500f, 0.063477f, 0.075684f, -0.1250f, -27.1250f, 30.0000f, 31, 27}, // c18c + {0.722168f, 0.569824f, 0.736816f, 0.584961f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c18d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c18e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c18f - {0.199707f, 0.541504f, 0.214355f, 0.556641f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c190 + {0.817383f, 0.570313f, 0.832031f, 0.585449f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c190 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c191 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c192 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c193 - {0.276367f, 0.541992f, 0.291016f, 0.557129f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c194 + {0.925293f, 0.570313f, 0.939941f, 0.585449f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c194 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c195 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c196 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c197 @@ -27652,7 +27953,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c19e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c19f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c1a0 - {0.324219f, 0.544922f, 0.338867f, 0.560059f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c1a1 + {0.496582f, 0.570801f, 0.511230f, 0.585938f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // c1a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c1a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c1a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c1a4 @@ -27771,7 +28072,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c215 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c216 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c217 - {0.339355f, 0.544922f, 0.354004f, 0.560059f, 0.3750f, -28.9375f, 30.0000f, 30, 31}, // c218 + {0.907227f, 0.570801f, 0.921875f, 0.585938f, 0.3750f, -28.9375f, 30.0000f, 30, 31}, // c218 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c219 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c21a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c21b @@ -27911,7 +28212,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a3 - {0.941895f, 0.693359f, 0.957031f, 0.705566f, -0.3125f, -26.2500f, 30.0000f, 31, 25}, // c2a4 + {0.011230f, 0.736328f, 0.026367f, 0.748535f, -0.3125f, -26.2500f, 30.0000f, 31, 25}, // c2a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2a7 @@ -27928,7 +28229,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b4 - {0.761230f, 0.600586f, 0.775879f, 0.615234f, 0.3125f, -28.0625f, 30.0000f, 30, 30}, // c2b5 + {0.149902f, 0.627930f, 0.164551f, 0.642578f, 0.3125f, -28.0625f, 30.0000f, 30, 30}, // c2b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2b8 @@ -27967,15 +28268,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2db - {0.415527f, 0.568848f, 0.429688f, 0.584473f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c2dc - {0.512695f, 0.568848f, 0.526855f, 0.584473f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2dd + {0.336914f, 0.594238f, 0.351074f, 0.609863f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c2dc + {0.636230f, 0.594238f, 0.650391f, 0.609863f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2df - {0.947754f, 0.617188f, 0.961914f, 0.632324f, 1.0625f, -29.3125f, 30.0000f, 29, 31}, // c2e0 + {0.165039f, 0.647461f, 0.179199f, 0.662598f, 1.0625f, -29.3125f, 30.0000f, 29, 31}, // c2e0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e3 - {0.781250f, 0.568848f, 0.795410f, 0.584473f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2e4 + {0.751953f, 0.594238f, 0.766113f, 0.609863f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2e4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e7 @@ -27983,12 +28284,12 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2eb - {0.830566f, 0.568848f, 0.844727f, 0.584473f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2ec - {0.182129f, 0.569336f, 0.196289f, 0.584961f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2ed + {0.198242f, 0.594727f, 0.212402f, 0.610352f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2ec + {0.060059f, 0.595215f, 0.074219f, 0.610840f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // c2ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2ef {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2f0 - {0.399414f, 0.569336f, 0.413574f, 0.584961f, 1.1875f, -29.2500f, 30.0000f, 29, 32}, // c2f1 + {0.461426f, 0.595215f, 0.475586f, 0.610840f, 1.1875f, -29.2500f, 30.0000f, 29, 32}, // c2f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c2f4 @@ -28499,7 +28800,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4ef - {0.228027f, 0.693848f, 0.243164f, 0.706055f, -0.3125f, -25.6875f, 30.0000f, 31, 25}, // c4f0 + {0.247559f, 0.738281f, 0.262695f, 0.750488f, -0.3125f, -25.6875f, 30.0000f, 31, 25}, // c4f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c4f3 @@ -28583,13 +28884,13 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c541 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c542 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c543 - {0.732422f, 0.569336f, 0.746582f, 0.584961f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // c544 - {0.763184f, 0.569336f, 0.777344f, 0.584961f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c545 + {0.650879f, 0.595215f, 0.665039f, 0.610840f, 1.2500f, -29.3125f, 30.0000f, 29, 32}, // c544 + {0.044922f, 0.595703f, 0.059082f, 0.611328f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c545 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c546 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c547 - {0.354492f, 0.544922f, 0.369141f, 0.560059f, 1.0000f, -29.3125f, 30.0000f, 30, 31}, // c548 + {0.955566f, 0.570801f, 0.970215f, 0.585938f, 1.0000f, -29.3125f, 30.0000f, 30, 31}, // c548 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c549 - {0.091309f, 0.569824f, 0.105469f, 0.585449f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c54a + {0.074707f, 0.595703f, 0.088867f, 0.611328f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c54a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c54b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c54c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c54d @@ -28600,7 +28901,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c552 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c553 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c554 - {0.229492f, 0.569824f, 0.243652f, 0.585449f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c555 + {0.121094f, 0.595703f, 0.135254f, 0.611328f, 1.3750f, -29.2500f, 30.0000f, 29, 32}, // c555 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c556 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c557 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c558 @@ -28619,7 +28920,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c565 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c566 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c567 - {0.290039f, 0.569824f, 0.304199f, 0.585449f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c568 + {0.506348f, 0.595703f, 0.520508f, 0.611328f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c568 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c569 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c56a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c56b @@ -28695,14 +28996,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b3 - {0.384277f, 0.569824f, 0.398438f, 0.585449f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c5b4 + {0.555664f, 0.595703f, 0.569824f, 0.611328f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c5b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b7 - {0.441406f, 0.617676f, 0.455566f, 0.632813f, 0.5625f, -29.2500f, 30.0000f, 29, 31}, // c5b8 + {0.704590f, 0.647461f, 0.718750f, 0.662598f, 0.5625f, -29.2500f, 30.0000f, 29, 31}, // c5b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ba - {0.869141f, 0.617676f, 0.883301f, 0.632813f, 0.6250f, -29.2500f, 30.0000f, 29, 31}, // c5bb + {0.791992f, 0.647949f, 0.806152f, 0.663086f, 0.6250f, -29.2500f, 30.0000f, 29, 31}, // c5bb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5be @@ -28712,10 +29013,10 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5c3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5c4 - {0.605469f, 0.569824f, 0.619629f, 0.585449f, 0.6250f, -29.2500f, 30.0000f, 29, 32}, // c5c5 - {0.650391f, 0.475098f, 0.665039f, 0.490723f, 0.6250f, -29.2500f, 30.0000f, 30, 32}, // c5c6 + {0.182617f, 0.596191f, 0.196777f, 0.611816f, 0.6250f, -29.2500f, 30.0000f, 29, 32}, // c5c5 + {0.954102f, 0.494629f, 0.968750f, 0.510254f, 0.6250f, -29.2500f, 30.0000f, 30, 32}, // c5c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5c7 - {0.811035f, 0.475098f, 0.825684f, 0.490723f, 0.6250f, -29.2500f, 30.0000f, 30, 32}, // c5c8 + {0.905273f, 0.495117f, 0.919922f, 0.510742f, 0.6250f, -29.2500f, 30.0000f, 30, 32}, // c5c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5cb @@ -28723,7 +29024,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5cf - {0.651367f, 0.569824f, 0.665527f, 0.585449f, 0.5625f, -29.3125f, 30.0000f, 29, 32}, // c5d0 + {0.029785f, 0.596680f, 0.043945f, 0.612305f, 0.5625f, -29.3125f, 30.0000f, 29, 32}, // c5d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5d3 @@ -28751,15 +29052,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5eb - {0.845215f, 0.569824f, 0.859375f, 0.585449f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c5ec - {0.976563f, 0.569824f, 0.990723f, 0.585449f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c5ed + {0.152832f, 0.596680f, 0.166992f, 0.612305f, 0.7500f, -29.2500f, 30.0000f, 29, 32}, // c5ec + {0.476074f, 0.596680f, 0.490234f, 0.612305f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c5ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ef - {0.228516f, 0.618164f, 0.242676f, 0.633301f, 0.5625f, -29.3125f, 30.0000f, 29, 31}, // c5f0 + {0.905762f, 0.647949f, 0.919922f, 0.663086f, 0.5625f, -29.3125f, 30.0000f, 29, 31}, // c5f0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f3 - {0.074707f, 0.570313f, 0.088867f, 0.585938f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c5f4 + {0.520996f, 0.596680f, 0.535156f, 0.612305f, 0.6250f, -29.3125f, 30.0000f, 29, 32}, // c5f4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5f7 @@ -28771,7 +29072,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c5ff - {0.843262f, 0.475098f, 0.857910f, 0.490723f, 0.6250f, -29.3125f, 30.0000f, 30, 32}, // c600 + {0.856934f, 0.495605f, 0.871582f, 0.511230f, 0.6250f, -29.3125f, 30.0000f, 30, 32}, // c600 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c601 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c602 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c603 @@ -28779,7 +29080,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c605 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c606 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c607 - {0.214355f, 0.570313f, 0.228516f, 0.585938f, 0.5625f, -29.3125f, 30.0000f, 29, 32}, // c608 + {0.535645f, 0.596680f, 0.549805f, 0.612305f, 0.5625f, -29.3125f, 30.0000f, 29, 32}, // c608 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c609 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c60a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c60b @@ -28807,15 +29108,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c621 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c622 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c623 - {0.329590f, 0.669434f, 0.344727f, 0.682617f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // c624 - {0.000000f, 0.546387f, 0.014648f, 0.561523f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c625 + {0.209473f, 0.109375f, 0.224609f, 0.122559f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // c624 + {0.260254f, 0.571777f, 0.274902f, 0.586914f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c625 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c626 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c627 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c628 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c629 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c62a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c62b - {0.107910f, 0.546387f, 0.122559f, 0.561523f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c62c + {0.786621f, 0.571777f, 0.801270f, 0.586914f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c62c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c62d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c62e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c62f @@ -28823,8 +29124,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c631 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c632 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c633 - {0.015137f, 0.548340f, 0.029785f, 0.563477f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c634 - {0.260254f, 0.549316f, 0.274902f, 0.564453f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c635 + {0.445801f, 0.572266f, 0.460449f, 0.587402f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c634 + {0.940430f, 0.572266f, 0.955078f, 0.587402f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c635 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c636 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c637 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c638 @@ -28839,7 +29140,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c641 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c642 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c643 - {0.802734f, 0.549316f, 0.817383f, 0.564453f, 0.1250f, -29.3125f, 30.0000f, 30, 31}, // c644 + {0.384766f, 0.572754f, 0.399414f, 0.587891f, 0.1250f, -29.3125f, 30.0000f, 30, 31}, // c644 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c645 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c646 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c647 @@ -28855,7 +29156,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c651 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c652 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c653 - {0.907715f, 0.475098f, 0.922363f, 0.490723f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // c654 + {0.392090f, 0.496094f, 0.406738f, 0.511719f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // c654 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c655 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c656 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c657 @@ -28895,7 +29196,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c679 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c67a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c67b - {0.817871f, 0.549316f, 0.832520f, 0.564453f, -0.1250f, -29.3125f, 30.0000f, 30, 31}, // c67c + {0.801758f, 0.572754f, 0.816406f, 0.587891f, -0.1250f, -29.3125f, 30.0000f, 30, 31}, // c67c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c67d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c67e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c67f @@ -28919,7 +29220,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c691 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c692 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c693 - {0.074707f, 0.670898f, 0.089844f, 0.684082f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // c694 + {0.418945f, 0.167480f, 0.434082f, 0.180664f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // c694 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c695 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c696 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c697 @@ -28940,7 +29241,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6a8 - {0.046387f, 0.549805f, 0.061035f, 0.564941f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c6a9 + {0.883301f, 0.572754f, 0.897949f, 0.587891f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c6a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6ab {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6ac @@ -28951,7 +29252,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b3 - {0.089355f, 0.601074f, 0.104004f, 0.615723f, 0.3125f, -27.8125f, 30.0000f, 30, 30}, // c6b4 + {0.470703f, 0.627930f, 0.485352f, 0.642578f, 0.3125f, -27.8125f, 30.0000f, 30, 30}, // c6b4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6b7 @@ -28963,7 +29264,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6bf - {0.061523f, 0.549805f, 0.076172f, 0.564941f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c6c0 + {0.307617f, 0.574219f, 0.322266f, 0.589355f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c6c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6c3 @@ -28979,7 +29280,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6cd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6ce {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6cf - {0.243164f, 0.618164f, 0.257324f, 0.633301f, 0.2500f, -29.2500f, 30.0000f, 29, 31}, // c6d0 + {0.486328f, 0.648438f, 0.500488f, 0.663574f, 0.2500f, -29.2500f, 30.0000f, 29, 31}, // c6d0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6d1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6d2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6d3 @@ -29003,7 +29304,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6e5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6e6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6e7 - {0.313477f, 0.475586f, 0.328125f, 0.491211f, -0.4375f, -29.3125f, 30.0000f, 30, 32}, // c6e8 + {0.817871f, 0.496094f, 0.832520f, 0.511719f, -0.4375f, -29.3125f, 30.0000f, 30, 32}, // c6e8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6eb @@ -29020,7 +29321,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6f6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6f7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6f8 - {0.423340f, 0.475586f, 0.437988f, 0.491211f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // c6f9 + {0.330566f, 0.496582f, 0.345215f, 0.512207f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // c6f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6fb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c6fc @@ -29031,7 +29332,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c701 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c702 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c703 - {0.619141f, 0.475586f, 0.633789f, 0.491211f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // c704 + {0.375977f, 0.496582f, 0.390625f, 0.512207f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // c704 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c705 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c706 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c707 @@ -29059,8 +29360,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c71d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c71e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c71f - {0.226563f, 0.601074f, 0.241211f, 0.615723f, 0.1250f, -27.8125f, 30.0000f, 30, 30}, // c720 - {0.153320f, 0.549805f, 0.167969f, 0.564941f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c721 + {0.516602f, 0.627930f, 0.531250f, 0.642578f, 0.1250f, -27.8125f, 30.0000f, 30, 30}, // c720 + {0.356934f, 0.574219f, 0.371582f, 0.589355f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c721 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c722 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c723 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c724 @@ -29080,22 +29381,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c732 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c733 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c734 - {0.030273f, 0.551270f, 0.044922f, 0.566406f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c735 + {0.832520f, 0.574219f, 0.847168f, 0.589355f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c735 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c736 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c737 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c738 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c739 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c73a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c73b - {0.292969f, 0.693848f, 0.308105f, 0.706055f, -0.3125f, -26.0000f, 30.0000f, 31, 25}, // c73c + {0.382324f, 0.738281f, 0.397461f, 0.750488f, -0.3125f, -26.0000f, 30.0000f, 31, 25}, // c73c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c73d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c73e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c73f - {0.289063f, 0.601074f, 0.303711f, 0.615723f, 0.3125f, -27.8125f, 30.0000f, 30, 30}, // c740 + {0.531738f, 0.627930f, 0.546387f, 0.642578f, 0.3125f, -27.8125f, 30.0000f, 30, 30}, // c740 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c741 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c742 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c743 - {0.530273f, 0.551270f, 0.544922f, 0.566406f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c744 + {0.669434f, 0.574707f, 0.684082f, 0.589844f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c744 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c745 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c746 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c747 @@ -29103,7 +29404,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c749 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c74a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c74b - {0.671875f, 0.551758f, 0.686523f, 0.566895f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c74c + {0.970703f, 0.574707f, 0.985352f, 0.589844f, 0.3125f, -28.2500f, 30.0000f, 30, 31}, // c74c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c74d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c74e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c74f @@ -29115,7 +29416,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c755 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c756 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c757 - {0.077637f, 0.476563f, 0.092285f, 0.492188f, 0.0000f, -29.3125f, 30.0000f, 30, 32}, // c758 + {0.679199f, 0.497070f, 0.693848f, 0.512695f, 0.0000f, -29.3125f, 30.0000f, 30, 32}, // c758 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c759 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c75a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c75b @@ -29143,27 +29444,27 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c771 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c772 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c773 - {0.380371f, 0.631348f, 0.394043f, 0.646973f, 2.0000f, -29.3125f, 30.0000f, 28, 32}, // c774 + {0.529297f, 0.658691f, 0.542969f, 0.674316f, 2.0000f, -29.3125f, 30.0000f, 28, 32}, // c774 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c775 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c776 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c777 - {0.077148f, 0.655273f, 0.090820f, 0.670410f, 1.2500f, -29.3125f, 30.0000f, 28, 31}, // c778 + {0.088379f, 0.686523f, 0.102051f, 0.701660f, 1.2500f, -29.3125f, 30.0000f, 28, 31}, // c778 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c779 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c77a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c77b - {0.707031f, 0.631348f, 0.720703f, 0.646973f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c77c - {0.756836f, 0.631348f, 0.770508f, 0.646973f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c77d + {0.014648f, 0.659180f, 0.028320f, 0.674805f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c77c + {0.226074f, 0.659180f, 0.239746f, 0.674805f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c77d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c77e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c77f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c780 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c781 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c782 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c783 - {0.119629f, 0.631836f, 0.133301f, 0.647461f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c784 - {0.364258f, 0.631836f, 0.377930f, 0.647461f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c785 + {0.719238f, 0.659668f, 0.732910f, 0.675293f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c784 + {0.379883f, 0.660156f, 0.393555f, 0.675781f, 1.5625f, -29.2500f, 30.0000f, 28, 32}, // c785 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c786 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c787 - {0.137695f, 0.570801f, 0.151855f, 0.586426f, 1.5625f, -29.2500f, 30.0000f, 29, 32}, // c788 + {0.604980f, 0.596680f, 0.619141f, 0.612305f, 1.5625f, -29.2500f, 30.0000f, 29, 32}, // c788 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c789 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c78a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c78b @@ -29171,8 +29472,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c78d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c78e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c78f - {0.184570f, 0.476563f, 0.199219f, 0.492188f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // c790 - {0.394043f, 0.476563f, 0.408691f, 0.492188f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c791 + {0.872070f, 0.497070f, 0.886719f, 0.512695f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // c790 + {0.600098f, 0.497559f, 0.614746f, 0.513184f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c791 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c792 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c793 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c794 @@ -29187,19 +29488,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c79d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c79e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c79f - {0.471680f, 0.476563f, 0.486328f, 0.492188f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c7a0 + {0.887207f, 0.497559f, 0.901855f, 0.513184f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c7a0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a4 - {0.727539f, 0.476563f, 0.742188f, 0.492188f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c7a5 + {0.345703f, 0.499023f, 0.360352f, 0.514648f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c7a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7a9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7aa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7ab - {0.742676f, 0.476563f, 0.757324f, 0.492188f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c7ac + {0.093750f, 0.499512f, 0.108398f, 0.515137f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c7ac {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7ad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7ae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7af @@ -29283,15 +29584,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c7ff - {0.794922f, 0.476563f, 0.809570f, 0.492188f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // c800 - {0.430176f, 0.570801f, 0.444336f, 0.586426f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c801 + {0.296875f, 0.500000f, 0.311523f, 0.515625f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // c800 + {0.014648f, 0.597168f, 0.028809f, 0.612793f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c801 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c802 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c803 - {0.702637f, 0.551758f, 0.717285f, 0.566895f, 0.1250f, -29.2500f, 30.0000f, 30, 31}, // c804 + {0.591797f, 0.575195f, 0.606445f, 0.590332f, 0.1250f, -29.2500f, 30.0000f, 30, 31}, // c804 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c805 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c806 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c807 - {0.092773f, 0.477051f, 0.107422f, 0.492676f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c808 + {0.312012f, 0.500000f, 0.326660f, 0.515625f, 0.4375f, -29.2500f, 30.0000f, 30, 32}, // c808 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c809 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c80a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c80b @@ -29299,19 +29600,19 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c80d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c80e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c80f - {0.463867f, 0.570801f, 0.478027f, 0.586426f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c810 - {0.496094f, 0.570801f, 0.510254f, 0.586426f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c811 + {0.135742f, 0.597168f, 0.149902f, 0.612793f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c810 + {0.732422f, 0.597656f, 0.746582f, 0.613281f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c811 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c812 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c813 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c814 - {0.588867f, 0.570801f, 0.603027f, 0.586426f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c815 + {0.230469f, 0.598145f, 0.244629f, 0.613770f, 0.4375f, -29.2500f, 30.0000f, 29, 32}, // c815 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c816 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c817 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c818 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c819 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c81a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c81b - {0.124023f, 0.477051f, 0.138672f, 0.492676f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c81c + {0.360840f, 0.500000f, 0.375488f, 0.515625f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c81c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c81d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c81e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c81f @@ -29395,11 +29696,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c86d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c86e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c86f - {0.086426f, 0.684570f, 0.101563f, 0.697266f, -0.1250f, -26.2500f, 30.0000f, 31, 26}, // c870 + {0.901855f, 0.721680f, 0.916992f, 0.734375f, -0.1250f, -26.2500f, 30.0000f, 31, 26}, // c870 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c871 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c872 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c873 - {0.369629f, 0.601074f, 0.384277f, 0.615723f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c874 + {0.595703f, 0.627930f, 0.610352f, 0.642578f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c874 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c875 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c876 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c877 @@ -29416,7 +29717,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c882 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c883 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c884 - {0.603027f, 0.601074f, 0.617676f, 0.615723f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c885 + {0.015137f, 0.628418f, 0.029785f, 0.643066f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c885 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c886 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c887 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c888 @@ -29479,7 +29780,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c3 - {0.234375f, 0.477051f, 0.249023f, 0.492676f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c8c4 + {0.630859f, 0.500000f, 0.645508f, 0.515625f, -0.5000f, -29.3125f, 30.0000f, 30, 32}, // c8c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8c7 @@ -29535,7 +29836,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8fb - {0.648926f, 0.601074f, 0.663574f, 0.615723f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // c8fc + {0.135254f, 0.628418f, 0.149902f, 0.643066f, 0.3750f, -27.9375f, 30.0000f, 30, 30}, // c8fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c8ff @@ -29556,7 +29857,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c90e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c90f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c910 - {0.838379f, 0.601074f, 0.853027f, 0.615723f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c911 + {0.728516f, 0.628906f, 0.743164f, 0.643555f, 0.3125f, -27.9375f, 30.0000f, 30, 30}, // c911 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c912 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c913 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c914 @@ -29731,11 +30032,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9bf - {0.645996f, 0.631836f, 0.659668f, 0.647461f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // c9c0 + {0.934570f, 0.660156f, 0.948242f, 0.675781f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // c9c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c3 - {0.349609f, 0.618164f, 0.363770f, 0.633301f, 1.1250f, -29.3125f, 30.0000f, 29, 31}, // c9c4 + {0.882813f, 0.648438f, 0.896973f, 0.663574f, 1.1250f, -29.3125f, 30.0000f, 29, 31}, // c9c4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9c7 @@ -29759,7 +30060,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9db - {0.418945f, 0.169434f, 0.434570f, 0.185059f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // c9dc + {0.177246f, 0.189941f, 0.192871f, 0.205566f, -0.9375f, -29.3125f, 30.0000f, 32, 32}, // c9dc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // c9df @@ -29984,7 +30285,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // caba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cabb {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cabc - {0.967773f, 0.601074f, 0.982422f, 0.615723f, 0.3125f, -27.6250f, 30.0000f, 30, 30}, // cabd + {0.227539f, 0.629395f, 0.242188f, 0.644043f, 0.3125f, -27.6250f, 30.0000f, 30, 30}, // cabd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cabe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cabf {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cac0 @@ -30320,7 +30621,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc0b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc0c - {0.249512f, 0.477051f, 0.264160f, 0.492676f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // cc0d + {0.772461f, 0.500000f, 0.787109f, 0.515625f, -0.2500f, -29.2500f, 30.0000f, 30, 32}, // cc0d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc0e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc0f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc10 @@ -30459,7 +30760,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc97 - {0.620117f, 0.570801f, 0.634277f, 0.586426f, 0.5625f, -29.2500f, 30.0000f, 29, 32}, // cc98 + {0.386719f, 0.599121f, 0.400879f, 0.614746f, 0.5625f, -29.2500f, 30.0000f, 29, 32}, // cc98 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc99 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc9a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cc9b @@ -30571,7 +30872,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd05 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd06 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd07 - {0.786133f, 0.656738f, 0.801270f, 0.670410f, -0.1250f, -27.3125f, 30.0000f, 31, 28}, // cd08 + {0.059082f, 0.687012f, 0.074219f, 0.700684f, -0.1250f, -27.3125f, 30.0000f, 31, 28}, // cd08 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd09 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd0a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd0b @@ -30655,7 +30956,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd5b - {0.328613f, 0.477051f, 0.343262f, 0.492676f, -0.0625f, -29.3125f, 30.0000f, 30, 32}, // cd5c + {0.787598f, 0.500000f, 0.802246f, 0.515625f, -0.0625f, -29.3125f, 30.0000f, 30, 32}, // cd5c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd5d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd5e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd5f @@ -30712,7 +31013,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd93 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd94 - {0.168457f, 0.552246f, 0.183105f, 0.567383f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // cd95 + {0.847656f, 0.575195f, 0.862305f, 0.590332f, 0.3125f, -28.6875f, 30.0000f, 30, 31}, // cd95 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd96 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd97 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cd98 @@ -30739,7 +31040,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdad {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdae {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdaf - {0.502930f, 0.477051f, 0.517578f, 0.492676f, 0.0625f, -29.2500f, 30.0000f, 30, 32}, // cdb0 + {0.663086f, 0.501465f, 0.677734f, 0.517090f, 0.0625f, -29.2500f, 30.0000f, 30, 32}, // cdb0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdb1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdb2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdb3 @@ -30795,7 +31096,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cde5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cde6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cde7 - {0.518066f, 0.477051f, 0.532715f, 0.492676f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // cde8 + {0.202637f, 0.501953f, 0.217285f, 0.517578f, 0.0625f, -29.3125f, 30.0000f, 30, 32}, // cde8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cde9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cdeb @@ -30907,7 +31208,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce57 - {0.833496f, 0.631836f, 0.847168f, 0.647461f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // ce58 + {0.948730f, 0.660156f, 0.962402f, 0.675781f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // ce58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce5b @@ -30935,7 +31236,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce71 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce72 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce73 - {0.596191f, 0.477051f, 0.610840f, 0.492676f, 0.5000f, -29.3125f, 30.0000f, 30, 32}, // ce74 + {0.470215f, 0.501953f, 0.484863f, 0.517578f, 0.5000f, -29.3125f, 30.0000f, 30, 32}, // ce74 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce75 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce76 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce77 @@ -30963,7 +31264,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce8d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce8e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce8f - {0.716309f, 0.570801f, 0.730469f, 0.586426f, 0.3750f, -29.3125f, 30.0000f, 29, 32}, // ce90 + {0.401367f, 0.599121f, 0.415527f, 0.614746f, 0.3750f, -29.3125f, 30.0000f, 29, 32}, // ce90 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce91 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce92 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ce93 @@ -31051,11 +31352,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cee5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cee6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cee7 - {0.482910f, 0.552246f, 0.497559f, 0.567383f, 0.0625f, -29.2500f, 30.0000f, 30, 31}, // cee8 + {0.862793f, 0.575684f, 0.877441f, 0.590820f, 0.0625f, -29.2500f, 30.0000f, 30, 31}, // cee8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cee9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceeb - {0.634277f, 0.477051f, 0.648926f, 0.492676f, -0.0625f, -29.2500f, 30.0000f, 30, 32}, // ceec + {0.516602f, 0.501953f, 0.531250f, 0.517578f, -0.0625f, -29.2500f, 30.0000f, 30, 32}, // ceec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceef @@ -31063,7 +31364,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef3 - {0.776855f, 0.477051f, 0.791504f, 0.492676f, -0.0625f, -29.2500f, 30.0000f, 30, 32}, // cef4 + {0.566895f, 0.501953f, 0.581543f, 0.517578f, -0.0625f, -29.2500f, 30.0000f, 30, 32}, // cef4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cef7 @@ -31075,7 +31376,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cefd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cefe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // ceff - {0.122070f, 0.571289f, 0.136230f, 0.586914f, 0.8750f, -29.3125f, 30.0000f, 29, 32}, // cf00 + {0.570313f, 0.599121f, 0.584473f, 0.614746f, 0.8750f, -29.3125f, 30.0000f, 29, 32}, // cf00 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf01 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf02 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf03 @@ -31103,7 +31404,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf19 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf1a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf1b - {0.930176f, 0.571289f, 0.944336f, 0.586914f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // cf1c + {0.416016f, 0.599609f, 0.430176f, 0.615234f, 1.1250f, -29.2500f, 30.0000f, 29, 32}, // cf1c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf1d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf1e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf1f @@ -31159,11 +31460,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf51 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf52 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf53 - {0.102051f, 0.684570f, 0.117188f, 0.697266f, -0.1250f, -25.8125f, 30.0000f, 31, 26}, // cf54 + {0.027344f, 0.722168f, 0.042480f, 0.734863f, -0.1250f, -25.8125f, 30.0000f, 31, 26}, // cf54 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf55 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf56 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf57 - {0.132813f, 0.648926f, 0.147461f, 0.663086f, 0.3125f, -27.2500f, 30.0000f, 30, 29}, // cf58 + {0.859863f, 0.681641f, 0.874512f, 0.695801f, 0.3125f, -27.2500f, 30.0000f, 30, 29}, // cf58 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf59 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf5a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // cf5b @@ -31411,7 +31712,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d04d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d04e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d04f - {0.982910f, 0.601074f, 0.997559f, 0.615723f, 0.6250f, -27.8750f, 30.0000f, 30, 30}, // d050 + {0.365723f, 0.630371f, 0.380371f, 0.645020f, 0.6250f, -27.8750f, 30.0000f, 30, 30}, // d050 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d051 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d052 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d053 @@ -31439,15 +31740,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d069 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d06a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d06b - {0.420898f, 0.693848f, 0.436035f, 0.706055f, 0.0000f, -25.0625f, 30.0000f, 31, 25}, // d06c + {0.453613f, 0.738770f, 0.468750f, 0.750977f, 0.0000f, -25.0625f, 30.0000f, 31, 25}, // d06c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d06d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d06e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d06f - {0.239746f, 0.648926f, 0.254395f, 0.663086f, 0.3125f, -27.5625f, 30.0000f, 30, 29}, // d070 + {0.814941f, 0.682617f, 0.829590f, 0.696777f, 0.3125f, -27.5625f, 30.0000f, 30, 29}, // d070 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d071 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d072 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d073 - {0.060547f, 0.601563f, 0.075195f, 0.616211f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // d074 + {0.380859f, 0.630371f, 0.395508f, 0.645020f, 0.3125f, -27.5625f, 30.0000f, 30, 30}, // d074 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d075 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d076 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d077 @@ -31495,7 +31796,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a3 - {0.962402f, 0.631836f, 0.976074f, 0.647461f, 1.5625f, -29.3125f, 30.0000f, 28, 32}, // d0a4 + {0.363281f, 0.661133f, 0.376953f, 0.676758f, 1.5625f, -29.3125f, 30.0000f, 28, 32}, // d0a4 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0a7 @@ -31512,7 +31813,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b4 - {0.858398f, 0.477051f, 0.873047f, 0.492676f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // d0b5 + {0.031250f, 0.502441f, 0.045898f, 0.518066f, 0.0000f, -29.2500f, 30.0000f, 30, 32}, // d0b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0b8 @@ -31523,7 +31824,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0bf - {0.944824f, 0.571289f, 0.958984f, 0.586914f, 1.4375f, -29.3125f, 30.0000f, 29, 32}, // d0c0 + {0.212891f, 0.600098f, 0.227051f, 0.615723f, 1.4375f, -29.3125f, 30.0000f, 29, 32}, // d0c0 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c3 @@ -31531,7 +31832,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c7 - {0.959473f, 0.571289f, 0.973633f, 0.586914f, 1.4375f, -29.2500f, 30.0000f, 29, 32}, // d0c8 + {0.699219f, 0.600586f, 0.713379f, 0.616211f, 1.4375f, -29.2500f, 30.0000f, 29, 32}, // d0c8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0c9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0ca {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0cb @@ -31551,8 +31852,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0db - {0.048340f, 0.632324f, 0.062012f, 0.647949f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d0dc - {0.612305f, 0.632324f, 0.625977f, 0.647949f, 1.4375f, -29.2500f, 30.0000f, 28, 32}, // d0dd + {0.561523f, 0.661133f, 0.575195f, 0.676758f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d0dc + {0.394043f, 0.661621f, 0.407715f, 0.677246f, 1.4375f, -29.2500f, 30.0000f, 28, 32}, // d0dd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0de {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0df {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d0e0 @@ -31635,7 +31936,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d12d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d12e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d12f - {0.133789f, 0.632813f, 0.147461f, 0.648438f, 1.4375f, -29.2500f, 30.0000f, 28, 32}, // d130 + {0.210449f, 0.662109f, 0.224121f, 0.677734f, 1.4375f, -29.2500f, 30.0000f, 28, 32}, // d130 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d131 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d132 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d133 @@ -31643,7 +31944,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d135 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d136 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d137 - {0.444824f, 0.571777f, 0.458984f, 0.587402f, 1.4375f, -29.2500f, 30.0000f, 29, 32}, // d138 + {0.683594f, 0.601074f, 0.697754f, 0.616699f, 1.4375f, -29.2500f, 30.0000f, 29, 32}, // d138 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d139 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d13a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d13b @@ -31663,8 +31964,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d149 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d14a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d14b - {0.413574f, 0.632813f, 0.427246f, 0.648438f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d14c - {0.427734f, 0.632813f, 0.441406f, 0.648438f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d14d + {0.408203f, 0.662109f, 0.421875f, 0.677734f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d14c + {0.257324f, 0.662598f, 0.270996f, 0.678223f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d14d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d14e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d14f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d150 @@ -31679,7 +31980,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d159 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d15a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d15b - {0.456055f, 0.632813f, 0.469727f, 0.648438f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d15c + {0.668945f, 0.662598f, 0.682617f, 0.678223f, 1.4375f, -29.3125f, 30.0000f, 28, 32}, // d15c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d15d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d15e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d15f @@ -31768,7 +32069,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b4 - {0.545410f, 0.552246f, 0.560059f, 0.567383f, 0.3125f, -28.0000f, 30.0000f, 30, 31}, // d1b5 + {0.322754f, 0.576172f, 0.337402f, 0.591309f, 0.3125f, -28.0000f, 30.0000f, 30, 31}, // d1b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b7 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d1b8 @@ -31887,7 +32188,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d229 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d22a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d22b - {0.197754f, 0.601563f, 0.212402f, 0.616211f, 0.4375f, -27.6875f, 30.0000f, 30, 30}, // d22c + {0.565918f, 0.630371f, 0.580566f, 0.645020f, 0.4375f, -27.6875f, 30.0000f, 30, 30}, // d22c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d22d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d22e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d22f @@ -31895,7 +32196,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d231 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d232 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d233 - {0.136230f, 0.602051f, 0.150879f, 0.616699f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d234 + {0.937500f, 0.630371f, 0.952148f, 0.645020f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d234 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d235 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d236 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d237 @@ -32027,11 +32328,11 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2b5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2b6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2b7 - {0.398926f, 0.694824f, 0.414063f, 0.707031f, -0.3125f, -25.6250f, 30.0000f, 31, 25}, // d2b8 + {0.866211f, 0.738770f, 0.881348f, 0.750977f, -0.3125f, -25.6250f, 30.0000f, 31, 25}, // d2b8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2b9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2ba {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2bb - {0.429199f, 0.602051f, 0.443848f, 0.616699f, 0.3125f, -27.7500f, 30.0000f, 30, 30}, // d2bc + {0.952637f, 0.630371f, 0.967285f, 0.645020f, 0.3125f, -27.7500f, 30.0000f, 30, 30}, // d2bc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2bd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2be {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2bf @@ -32083,8 +32384,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2ef - {0.488770f, 0.632813f, 0.502441f, 0.648438f, 1.7500f, -29.3125f, 30.0000f, 28, 32}, // d2f0 - {0.577148f, 0.632813f, 0.590820f, 0.648438f, 1.8750f, -29.2500f, 30.0000f, 28, 32}, // d2f1 + {0.683105f, 0.662598f, 0.696777f, 0.678223f, 1.7500f, -29.3125f, 30.0000f, 28, 32}, // d2f0 + {0.000000f, 0.663086f, 0.013672f, 0.678711f, 1.8750f, -29.2500f, 30.0000f, 28, 32}, // d2f1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2f2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2f3 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d2f4 @@ -32111,7 +32412,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d309 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d30a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d30b - {0.951660f, 0.477051f, 0.966309f, 0.492676f, 0.5000f, -29.3125f, 30.0000f, 30, 32}, // d30c + {0.046387f, 0.502441f, 0.061035f, 0.518066f, 0.5000f, -29.3125f, 30.0000f, 30, 32}, // d30c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d30d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d30e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d30f @@ -32139,7 +32440,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d325 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d326 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d327 - {0.966797f, 0.477051f, 0.981445f, 0.492676f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // d328 + {0.078613f, 0.502441f, 0.093262f, 0.518066f, 0.1875f, -29.3125f, 30.0000f, 30, 32}, // d328 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d329 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d32a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d32b @@ -32223,7 +32524,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d379 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d37a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d37b - {0.878418f, 0.571777f, 0.892578f, 0.587402f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d37c + {0.000000f, 0.601563f, 0.014160f, 0.617188f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d37c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d37d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d37e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d37f @@ -32335,7 +32636,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3e9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3ea {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3eb - {0.779785f, 0.684570f, 0.794922f, 0.697266f, -0.1875f, -25.7500f, 30.0000f, 31, 26}, // d3ec + {0.125488f, 0.722168f, 0.140625f, 0.734863f, -0.1875f, -25.7500f, 30.0000f, 31, 26}, // d3ec {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3ed {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3ee {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3ef @@ -32351,7 +32652,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3f9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3fa {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3fb - {0.459473f, 0.602051f, 0.474121f, 0.616699f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d3fc + {0.395996f, 0.630859f, 0.410645f, 0.645508f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d3fc {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3fd {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3fe {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d3ff @@ -32447,7 +32748,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d459 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d45a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d45b - {0.513184f, 0.687988f, 0.528320f, 0.700684f, -0.2500f, -26.1875f, 30.0000f, 31, 26}, // d45c + {0.141113f, 0.722168f, 0.156250f, 0.734863f, -0.2500f, -26.1875f, 30.0000f, 31, 26}, // d45c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d45d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d45e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d45f @@ -32483,7 +32784,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d47d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d47e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d47f - {0.489746f, 0.602051f, 0.504395f, 0.616699f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d480 + {0.212402f, 0.631348f, 0.227051f, 0.645996f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d480 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d481 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d482 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d483 @@ -32615,7 +32916,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d501 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d502 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d503 - {0.436523f, 0.694824f, 0.451660f, 0.707031f, -0.3125f, -25.7500f, 30.0000f, 31, 25}, // d504 + {0.543945f, 0.739258f, 0.559082f, 0.751465f, -0.3125f, -25.7500f, 30.0000f, 31, 25}, // d504 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d505 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d506 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d507 @@ -32623,7 +32924,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d509 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d50a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d50b - {0.586426f, 0.602051f, 0.601074f, 0.616699f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d50c + {0.695801f, 0.631836f, 0.710449f, 0.646484f, 0.3125f, -28.0000f, 30.0000f, 30, 30}, // d50c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d50d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d50e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d50f @@ -32672,14 +32973,14 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d53a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d53b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d53c - {0.907715f, 0.571777f, 0.921875f, 0.587402f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d53d + {0.167480f, 0.601563f, 0.181641f, 0.617188f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d53d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d53e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d53f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d540 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d541 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d542 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d543 - {0.244141f, 0.572266f, 0.258301f, 0.587891f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d544 + {0.713867f, 0.601563f, 0.728027f, 0.617188f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d544 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d545 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d546 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d547 @@ -32692,22 +32993,22 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d54e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d54f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d550 - {0.366211f, 0.572266f, 0.380371f, 0.587891f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d551 + {0.814941f, 0.602051f, 0.829102f, 0.617676f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d551 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d552 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d553 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d554 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d555 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d556 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d557 - {0.981934f, 0.477051f, 0.996582f, 0.492676f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // d558 + {0.187988f, 0.502441f, 0.202637f, 0.518066f, 0.8125f, -29.3125f, 30.0000f, 30, 32}, // d558 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d559 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d55a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d55b - {0.560547f, 0.552246f, 0.575195f, 0.567383f, 0.5625f, -29.3125f, 30.0000f, 30, 31}, // d55c + {0.106934f, 0.577148f, 0.121582f, 0.592285f, 0.5625f, -29.3125f, 30.0000f, 30, 31}, // d55c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d55d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d55e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d55f - {0.139160f, 0.477539f, 0.153809f, 0.493164f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d560 + {0.485352f, 0.502441f, 0.500000f, 0.518066f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d560 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d561 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d562 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d563 @@ -32716,18 +33017,18 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d566 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d567 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d568 - {0.375977f, 0.477539f, 0.390625f, 0.493164f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d569 + {0.615234f, 0.502441f, 0.629883f, 0.518066f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d569 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d56a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d56b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d56c - {0.438477f, 0.477539f, 0.453125f, 0.493164f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d56d + {0.061523f, 0.502930f, 0.076172f, 0.518555f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d56d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d56e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d56f {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d570 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d571 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d572 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d573 - {0.859863f, 0.572266f, 0.874023f, 0.587891f, 0.3125f, -29.3125f, 30.0000f, 29, 32}, // d574 + {0.913086f, 0.602051f, 0.927246f, 0.617676f, 0.3125f, -29.3125f, 30.0000f, 29, 32}, // d574 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d575 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d576 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d577 @@ -32747,8 +33048,8 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d585 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d586 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d587 - {0.453613f, 0.477539f, 0.468262f, 0.493164f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d588 - {0.683594f, 0.572754f, 0.697754f, 0.588379f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d589 + {0.531738f, 0.502930f, 0.546387f, 0.518555f, 0.5000f, -29.2500f, 30.0000f, 30, 32}, // d588 + {0.490723f, 0.602539f, 0.504883f, 0.618164f, 0.5000f, -29.2500f, 30.0000f, 29, 32}, // d589 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d58a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d58b {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d58c @@ -32827,7 +33128,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5d5 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5d6 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5d7 - {0.196777f, 0.573242f, 0.210938f, 0.588867f, 0.5000f, -29.3125f, 30.0000f, 29, 32}, // d5d8 + {0.892578f, 0.602539f, 0.906738f, 0.618164f, 0.5000f, -29.3125f, 30.0000f, 29, 32}, // d5d8 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5d9 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5da {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d5db @@ -32888,7 +33189,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d612 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d613 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d614 - {0.922852f, 0.477539f, 0.937500f, 0.493164f, 0.2500f, -29.3125f, 30.0000f, 30, 32}, // d615 + {0.645996f, 0.502930f, 0.660645f, 0.518555f, 0.2500f, -29.3125f, 30.0000f, 30, 32}, // d615 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d616 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d617 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d618 @@ -32923,7 +33224,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d635 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d636 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d637 - {0.783203f, 0.670898f, 0.798340f, 0.684082f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // d638 + {0.483398f, 0.180664f, 0.498535f, 0.193848f, -0.1875f, -26.9375f, 30.0000f, 31, 27}, // d638 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d639 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d63a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d63b @@ -32939,7 +33240,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d645 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d646 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d647 - {0.575684f, 0.552246f, 0.590332f, 0.567383f, 0.3125f, -28.6250f, 30.0000f, 30, 31}, // d648 + {0.622559f, 0.577148f, 0.637207f, 0.592285f, 0.3125f, -28.6250f, 30.0000f, 30, 31}, // d648 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d649 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d64a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d64b @@ -32951,15 +33252,15 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d651 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d652 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d653 - {0.528809f, 0.350586f, 0.543945f, 0.366211f, 0.0000f, -29.3125f, 30.0000f, 31, 32}, // d654 - {0.264648f, 0.478027f, 0.279297f, 0.493652f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // d655 + {0.382813f, 0.370117f, 0.397949f, 0.385742f, 0.0000f, -29.3125f, 30.0000f, 31, 32}, // d654 + {0.141113f, 0.503418f, 0.155762f, 0.519043f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // d655 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d656 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d657 - {0.639160f, 0.552246f, 0.653809f, 0.567383f, 0.1250f, -29.3125f, 30.0000f, 30, 31}, // d658 + {0.770508f, 0.577148f, 0.785156f, 0.592285f, 0.1250f, -29.3125f, 30.0000f, 30, 31}, // d658 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d659 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d65a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d65b - {0.694824f, 0.478027f, 0.709473f, 0.493652f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // d65c + {0.156250f, 0.503418f, 0.170898f, 0.519043f, 0.2500f, -29.2500f, 30.0000f, 30, 32}, // d65c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d65d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d65e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d65f @@ -33231,7 +33532,7 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d769 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d76a {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d76b - {0.873535f, 0.478027f, 0.888184f, 0.493652f, 0.0000f, -29.3125f, 30.0000f, 30, 32}, // d76c + {0.546875f, 0.503418f, 0.561523f, 0.519043f, 0.0000f, -29.3125f, 30.0000f, 30, 32}, // d76c {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d76d {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d76e {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d76f @@ -33287,247 +33588,247 @@ const AtlasChar font_UBUNTU24_chardata[] = { {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d7a1 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d7a2 {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0000f, -2.0000f, 0.0000f, 0, 0}, // d7a3 -// RANGE: 0xff00 - 0xfff0, start 0x820c - {0.435059f, 0.738281f, 0.448242f, 0.751465f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff00 - {0.687500f, 0.210938f, 0.691406f, 0.223633f, 11.3125f, -25.5000f, 30.0000f, 8, 26}, // ff01 - {0.664063f, 0.675293f, 0.670410f, 0.681152f, 8.8750f, -25.5000f, 30.0000f, 13, 12}, // ff02 - {0.547363f, 0.785156f, 0.557617f, 0.798340f, 5.0000f, -25.8750f, 30.0000f, 21, 27}, // ff03 - {0.000000f, 0.776855f, 0.009277f, 0.791992f, 5.8125f, -27.5000f, 30.0000f, 19, 31}, // ff04 - {0.664063f, 0.738770f, 0.677246f, 0.751953f, 1.8125f, -25.8750f, 30.0000f, 27, 27}, // ff05 - {0.512695f, 0.766602f, 0.523926f, 0.779785f, 3.9375f, -25.8750f, 30.0000f, 23, 27}, // ff06 - {0.315918f, 0.226074f, 0.319824f, 0.231934f, 11.3750f, -25.5000f, 30.0000f, 8, 12}, // ff07 - {0.586914f, 0.831543f, 0.592773f, 0.847656f, 9.4375f, -25.8750f, 30.0000f, 12, 33}, // ff08 - {0.289551f, 0.832031f, 0.295410f, 0.848145f, 9.4375f, -25.8750f, 30.0000f, 12, 33}, // ff09 - {0.109863f, 0.756836f, 0.116699f, 0.763672f, 8.1250f, -25.8750f, 30.0000f, 14, 14}, // ff0a - {0.262207f, 0.509277f, 0.271484f, 0.518555f, 5.8750f, -21.7500f, 30.0000f, 19, 19}, // ff0b - {0.680176f, 0.444824f, 0.684082f, 0.450684f, 11.3750f, -7.0625f, 30.0000f, 8, 12}, // ff0c - {0.006836f, 0.624023f, 0.013184f, 0.627441f, 9.0000f, -13.1250f, 30.0000f, 13, 7}, // ff0d - {0.934082f, 0.493652f, 0.937988f, 0.497559f, 11.4375f, -7.0625f, 30.0000f, 8, 8}, // ff0e - {0.126953f, 0.841797f, 0.133301f, 0.854980f, 8.8125f, -25.5000f, 30.0000f, 13, 27}, // ff0f - {0.943359f, 0.812012f, 0.952637f, 0.824707f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff10 - {0.111816f, 0.697754f, 0.117676f, 0.710449f, 9.0000f, -25.6250f, 30.0000f, 12, 26}, // ff11 - {0.953125f, 0.812012f, 0.962402f, 0.824707f, 5.8750f, -25.5625f, 30.0000f, 19, 26}, // ff12 - {0.374023f, 0.812500f, 0.383301f, 0.825195f, 6.0000f, -25.5625f, 30.0000f, 19, 26}, // ff13 - {0.544434f, 0.812500f, 0.553711f, 0.825195f, 5.5625f, -25.5000f, 30.0000f, 19, 26}, // ff14 - {0.915039f, 0.812500f, 0.924316f, 0.825195f, 5.8750f, -25.1875f, 30.0000f, 19, 26}, // ff15 - {0.962891f, 0.812500f, 0.972168f, 0.825195f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff16 - {0.595215f, 0.821777f, 0.604004f, 0.834473f, 6.0000f, -25.1875f, 30.0000f, 18, 26}, // ff17 - {0.176270f, 0.812988f, 0.185547f, 0.825684f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff18 - {0.245117f, 0.812988f, 0.254395f, 0.825684f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff19 - {0.413574f, 0.312012f, 0.417480f, 0.321777f, 11.4375f, -19.5625f, 30.0000f, 8, 20}, // ff1a - {0.493164f, 0.337891f, 0.497070f, 0.349609f, 11.4375f, -19.5625f, 30.0000f, 8, 24}, // ff1b - {0.196777f, 0.733887f, 0.206055f, 0.743164f, 5.8750f, -21.8750f, 30.0000f, 19, 19}, // ff1c - {0.306152f, 0.226074f, 0.315430f, 0.232910f, 5.8750f, -19.1250f, 30.0000f, 19, 14}, // ff1d - {0.806152f, 0.837891f, 0.815430f, 0.847168f, 5.8750f, -21.8750f, 30.0000f, 19, 19}, // ff1e - {0.617188f, 0.821777f, 0.625977f, 0.834473f, 6.0625f, -25.8750f, 30.0000f, 18, 26}, // ff1f - {0.699707f, 0.032227f, 0.715332f, 0.048340f, -0.9375f, -25.8750f, 30.0000f, 32, 33}, // ff20 - {0.764160f, 0.757324f, 0.776367f, 0.770020f, 2.9375f, -25.5000f, 30.0000f, 25, 26}, // ff21 - {0.258789f, 0.793945f, 0.269043f, 0.806641f, 4.8125f, -25.5000f, 30.0000f, 21, 26}, // ff22 - {0.616211f, 0.766602f, 0.627441f, 0.779785f, 3.5000f, -25.8750f, 30.0000f, 23, 27}, // ff23 - {0.783203f, 0.782715f, 0.793945f, 0.795410f, 4.0625f, -25.5000f, 30.0000f, 22, 26}, // ff24 - {0.659668f, 0.793945f, 0.669922f, 0.806641f, 4.9375f, -25.5000f, 30.0000f, 21, 26}, // ff25 - {0.126953f, 0.813477f, 0.136230f, 0.826172f, 5.6875f, -25.5000f, 30.0000f, 19, 26}, // ff26 - {0.306152f, 0.760254f, 0.317871f, 0.773438f, 3.0625f, -25.8750f, 30.0000f, 24, 27}, // ff27 - {0.670410f, 0.793945f, 0.680664f, 0.806641f, 4.5625f, -25.5000f, 30.0000f, 21, 26}, // ff28 - {0.767090f, 0.241211f, 0.770508f, 0.253906f, 11.5625f, -25.5000f, 30.0000f, 7, 26}, // ff29 - {0.636230f, 0.829590f, 0.644043f, 0.842285f, 7.1250f, -25.5000f, 30.0000f, 16, 26}, // ff2a - {0.884766f, 0.782715f, 0.895508f, 0.795410f, 4.0625f, -25.5000f, 30.0000f, 22, 26}, // ff2b - {0.799805f, 0.821777f, 0.808594f, 0.834473f, 6.2500f, -25.5000f, 30.0000f, 18, 26}, // ff2c - {0.474121f, 0.758301f, 0.486328f, 0.770996f, 2.7500f, -25.5000f, 30.0000f, 25, 26}, // ff2d - {0.681152f, 0.793945f, 0.691406f, 0.806641f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff2e - {0.022949f, 0.753418f, 0.035156f, 0.766602f, 2.6875f, -25.8750f, 30.0000f, 25, 27}, // ff2f - {0.848633f, 0.793945f, 0.858887f, 0.806641f, 4.7500f, -25.5000f, 30.0000f, 21, 26}, // ff30 - {0.932129f, 0.749512f, 0.944336f, 0.763184f, 2.5000f, -25.8750f, 30.0000f, 25, 28}, // ff31 - {0.487305f, 0.775879f, 0.498535f, 0.788574f, 3.5000f, -25.5000f, 30.0000f, 23, 26}, // ff32 - {0.796387f, 0.775879f, 0.807129f, 0.789063f, 4.4375f, -25.8750f, 30.0000f, 22, 27}, // ff33 - {0.161621f, 0.783203f, 0.172363f, 0.795898f, 4.4375f, -25.5000f, 30.0000f, 22, 26}, // ff34 - {0.905762f, 0.793945f, 0.916016f, 0.806641f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff35 - {0.687500f, 0.766113f, 0.699219f, 0.778809f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff36 - {0.514160f, 0.674805f, 0.529785f, 0.687500f, -0.8750f, -25.5000f, 30.0000f, 32, 26}, // ff37 - {0.852539f, 0.766113f, 0.864258f, 0.778809f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff38 - {0.909180f, 0.766113f, 0.920898f, 0.778809f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff39 - {0.101074f, 0.794922f, 0.111328f, 0.807617f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff3a - {0.245117f, 0.842773f, 0.250000f, 0.858398f, 10.0625f, -25.5000f, 30.0000f, 10, 32}, // ff3b - {0.446289f, 0.841797f, 0.452637f, 0.854980f, 8.8125f, -25.5000f, 30.0000f, 13, 27}, // ff3c - {0.791992f, 0.842773f, 0.796875f, 0.858398f, 10.0625f, -25.5000f, 30.0000f, 10, 32}, // ff3d - {0.402832f, 0.144043f, 0.411133f, 0.151855f, 6.6875f, -25.5000f, 30.0000f, 17, 16}, // ff3e - {0.714355f, 0.095703f, 0.724121f, 0.098633f, 5.3125f, -1.7500f, 30.0000f, 20, 6}, // ff3f - {0.099609f, 0.616211f, 0.104492f, 0.620605f, 10.2500f, -25.8750f, 30.0000f, 10, 9}, // ff40 - {0.475586f, 0.832520f, 0.484863f, 0.842773f, 5.8125f, -19.9375f, 30.0000f, 19, 21}, // ff41 - {0.820801f, 0.821777f, 0.829590f, 0.834473f, 6.1875f, -25.5000f, 30.0000f, 18, 26}, // ff42 - {0.017578f, 0.836914f, 0.026367f, 0.847168f, 6.1875f, -19.9375f, 30.0000f, 18, 21}, // ff43 - {0.856934f, 0.821777f, 0.865723f, 0.834473f, 6.1875f, -25.5000f, 30.0000f, 18, 26}, // ff44 - {0.702637f, 0.832520f, 0.711914f, 0.842773f, 5.8125f, -19.9375f, 30.0000f, 19, 21}, // ff45 - {0.749023f, 0.539063f, 0.755859f, 0.551758f, 8.4375f, -25.8750f, 30.0000f, 14, 26}, // ff46 - {0.458984f, 0.816406f, 0.467773f, 0.829590f, 6.1250f, -19.9375f, 30.0000f, 18, 27}, // ff47 - {0.562988f, 0.824707f, 0.571289f, 0.837402f, 6.6250f, -25.5000f, 30.0000f, 17, 26}, // ff48 - {0.508789f, 0.352539f, 0.512207f, 0.365234f, 11.6250f, -25.5000f, 30.0000f, 7, 26}, // ff49 - {0.050781f, 0.843262f, 0.055664f, 0.858887f, 10.0000f, -25.5000f, 30.0000f, 10, 32}, // ff4a - {0.809082f, 0.824707f, 0.817383f, 0.837402f, 6.5000f, -25.5000f, 30.0000f, 17, 26}, // ff4b - {0.540039f, 0.366699f, 0.543457f, 0.379395f, 11.6250f, -25.5000f, 30.0000f, 7, 26}, // ff4c - {0.488770f, 0.024414f, 0.501465f, 0.034180f, 2.4375f, -19.9375f, 30.0000f, 26, 20}, // ff4d - {0.147461f, 0.842773f, 0.155762f, 0.852539f, 6.6250f, -19.9375f, 30.0000f, 17, 20}, // ff4e - {0.764648f, 0.832520f, 0.773926f, 0.842773f, 5.6875f, -19.9375f, 30.0000f, 19, 21}, // ff4f - {0.934082f, 0.821777f, 0.942871f, 0.834473f, 6.1875f, -19.9375f, 30.0000f, 18, 26}, // ff50 - {0.972656f, 0.821777f, 0.981445f, 0.834473f, 6.1875f, -19.9375f, 30.0000f, 18, 26}, // ff51 - {0.957520f, 0.693359f, 0.963867f, 0.703125f, 8.7500f, -19.9375f, 30.0000f, 13, 20}, // ff52 - {0.091797f, 0.840332f, 0.100098f, 0.850586f, 6.5625f, -19.9375f, 30.0000f, 17, 21}, // ff53 - {0.082520f, 0.843262f, 0.088379f, 0.855957f, 9.1875f, -25.0000f, 30.0000f, 12, 26}, // ff54 - {0.631836f, 0.842773f, 0.640137f, 0.852539f, 6.6250f, -19.5625f, 30.0000f, 17, 20}, // ff55 - {0.827148f, 0.836426f, 0.836426f, 0.846191f, 5.8125f, -19.5625f, 30.0000f, 19, 20}, // ff56 - {0.475098f, 0.040527f, 0.487793f, 0.050293f, 2.3125f, -19.5625f, 30.0000f, 26, 20}, // ff57 - {0.845215f, 0.836426f, 0.854492f, 0.846191f, 5.6875f, -19.5625f, 30.0000f, 19, 20}, // ff58 - {0.271973f, 0.813477f, 0.281250f, 0.826172f, 5.8125f, -19.5625f, 30.0000f, 19, 26}, // ff59 - {0.056152f, 0.840332f, 0.064941f, 0.850098f, 6.0625f, -19.5625f, 30.0000f, 18, 20}, // ff5a - {0.175293f, 0.826172f, 0.181641f, 0.842285f, 8.7500f, -25.8750f, 30.0000f, 13, 33}, // ff5b - {0.951660f, 0.445313f, 0.955078f, 0.460938f, 11.8750f, -25.5000f, 30.0000f, 7, 32}, // ff5c - {0.245605f, 0.826172f, 0.251953f, 0.842285f, 8.7500f, -25.8750f, 30.0000f, 13, 33}, // ff5d - {0.222168f, 0.063477f, 0.231445f, 0.067871f, 5.5000f, -17.0000f, 30.0000f, 19, 9}, // ff5e - {0.677734f, 0.738770f, 0.690918f, 0.751953f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff5f - {0.691406f, 0.738770f, 0.704590f, 0.751953f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff60 - {0.816895f, 0.528320f, 0.821777f, 0.533203f, -0.4375f, -8.2500f, 15.0000f, 10, 10}, // ff61 - {0.412598f, 0.817383f, 0.419922f, 0.833008f, 0.3125f, -29.1250f, 15.0000f, 15, 32}, // ff62 - {0.429688f, 0.817383f, 0.437012f, 0.833008f, 0.3125f, -29.1250f, 15.0000f, 15, 32}, // ff63 - {0.457031f, 0.729980f, 0.462891f, 0.735840f, -0.3750f, -9.1875f, 15.0000f, 12, 12}, // ff64 - {0.275879f, 0.494141f, 0.279785f, 0.498047f, 3.8125f, -17.1875f, 15.0000f, 8, 8}, // ff65 - {0.018066f, 0.822266f, 0.025879f, 0.836426f, -0.0625f, -26.6250f, 15.0000f, 16, 29}, // ff66 - {0.912598f, 0.825684f, 0.920410f, 0.838867f, -0.1250f, -26.0000f, 15.0000f, 16, 27}, // ff67 - {0.830078f, 0.822266f, 0.837891f, 0.835938f, -0.6875f, -27.1250f, 15.0000f, 16, 28}, // ff68 - {0.133789f, 0.828125f, 0.141113f, 0.841797f, 0.3125f, -26.9375f, 15.0000f, 15, 28}, // ff69 - {0.102051f, 0.770020f, 0.109863f, 0.781738f, -0.1875f, -24.6875f, 15.0000f, 16, 24}, // ff6a - {0.082520f, 0.817871f, 0.090820f, 0.831543f, -0.8750f, -26.5625f, 15.0000f, 17, 28}, // ff6b - {0.791016f, 0.817871f, 0.799316f, 0.831543f, -0.5000f, -26.6875f, 15.0000f, 17, 28}, // ff6c - {0.536621f, 0.833496f, 0.544434f, 0.845215f, -0.1875f, -24.8750f, 15.0000f, 16, 24}, // ff6d - {0.192871f, 0.708008f, 0.200195f, 0.720215f, 0.3125f, -25.0625f, 15.0000f, 15, 25}, // ff6e - {0.756348f, 0.829590f, 0.764160f, 0.842285f, -0.3750f, -25.8125f, 15.0000f, 16, 26}, // ff6f - {0.907715f, 0.567871f, 0.915039f, 0.571289f, 0.3750f, -16.3750f, 15.0000f, 15, 7}, // ff70 - {0.720215f, 0.802734f, 0.729004f, 0.816895f, -0.7500f, -26.5625f, 15.0000f, 18, 29}, // ff71 - {0.848145f, 0.807129f, 0.856445f, 0.821777f, -0.8125f, -27.8750f, 15.0000f, 17, 30}, // ff72 - {0.866211f, 0.240723f, 0.874023f, 0.255371f, -0.1875f, -28.1250f, 15.0000f, 16, 30}, // ff73 - {0.648926f, 0.822266f, 0.657227f, 0.835449f, -0.7500f, -26.0625f, 15.0000f, 17, 27}, // ff74 - {0.868164f, 0.807129f, 0.876465f, 0.821777f, -1.0000f, -27.6875f, 15.0000f, 17, 30}, // ff75 - {0.906250f, 0.807129f, 0.914551f, 0.821777f, -0.8750f, -27.8750f, 15.0000f, 17, 30}, // ff76 - {0.100586f, 0.808105f, 0.108887f, 0.822754f, -0.7500f, -28.0000f, 15.0000f, 17, 30}, // ff77 - {0.611328f, 0.477051f, 0.619141f, 0.491699f, -0.8125f, -28.4375f, 15.0000f, 16, 30}, // ff78 - {0.109375f, 0.808105f, 0.117676f, 0.822754f, -0.8750f, -28.4375f, 15.0000f, 17, 30}, // ff79 - {0.962891f, 0.825684f, 0.970703f, 0.838867f, -0.2500f, -26.0625f, 15.0000f, 16, 27}, // ff7a - {0.742676f, 0.808105f, 0.750977f, 0.822754f, -0.7500f, -27.6875f, 15.0000f, 17, 30}, // ff7b - {0.395996f, 0.814453f, 0.404297f, 0.828613f, -0.9375f, -27.1250f, 15.0000f, 17, 29}, // ff7c - {0.158203f, 0.811523f, 0.166992f, 0.825195f, -1.1875f, -25.8125f, 15.0000f, 18, 28}, // ff7d - {0.468262f, 0.818359f, 0.476563f, 0.832031f, -0.6875f, -27.6250f, 15.0000f, 17, 28}, // ff7e - {0.210449f, 0.822266f, 0.218262f, 0.836426f, -0.5625f, -27.4375f, 15.0000f, 16, 29}, // ff7f - {0.040527f, 0.810059f, 0.048828f, 0.824707f, -0.9375f, -27.9375f, 15.0000f, 17, 30}, // ff80 - {0.263184f, 0.810059f, 0.271484f, 0.824707f, -0.7500f, -27.9375f, 15.0000f, 17, 30}, // ff81 - {0.751465f, 0.814453f, 0.759766f, 0.828613f, -0.6875f, -27.1250f, 15.0000f, 17, 29}, // ff82 - {0.640137f, 0.814941f, 0.648438f, 0.829102f, -0.7500f, -26.2500f, 15.0000f, 17, 29}, // ff83 - {0.591309f, 0.632813f, 0.598145f, 0.646973f, 1.6250f, -27.6250f, 15.0000f, 14, 29}, // ff84 - {0.118164f, 0.811035f, 0.126465f, 0.825684f, -0.7500f, -27.6250f, 15.0000f, 17, 30}, // ff85 - {0.705078f, 0.692871f, 0.713379f, 0.705078f, -0.7500f, -25.3750f, 15.0000f, 17, 25}, // ff86 - {0.477051f, 0.818359f, 0.485352f, 0.832031f, -0.7500f, -26.0625f, 15.0000f, 17, 28}, // ff87 - {0.474609f, 0.803711f, 0.483398f, 0.817871f, -1.2500f, -27.0625f, 15.0000f, 18, 29}, // ff88 - {0.848633f, 0.822266f, 0.856445f, 0.835938f, -0.5000f, -26.2500f, 15.0000f, 16, 28}, // ff89 - {0.839844f, 0.814941f, 0.848145f, 0.829102f, -1.0000f, -27.7500f, 15.0000f, 17, 29}, // ff8a - {0.866211f, 0.822266f, 0.874023f, 0.835938f, 0.8125f, -27.1250f, 15.0000f, 16, 28}, // ff8b - {0.904297f, 0.822266f, 0.912109f, 0.835938f, -0.0625f, -26.0000f, 15.0000f, 16, 28}, // ff8c - {0.715820f, 0.831543f, 0.724609f, 0.842773f, -1.2500f, -23.3750f, 15.0000f, 18, 23}, // ff8d - {0.483887f, 0.803711f, 0.492676f, 0.817871f, -1.3750f, -27.5625f, 15.0000f, 18, 29}, // ff8e - {0.657715f, 0.822266f, 0.666016f, 0.835449f, -0.5625f, -25.8750f, 15.0000f, 17, 27}, // ff8f - {0.027344f, 0.815430f, 0.035645f, 0.829590f, -0.8750f, -27.1250f, 15.0000f, 17, 29}, // ff90 - {0.054199f, 0.804199f, 0.062988f, 0.818359f, -1.1875f, -27.7500f, 15.0000f, 18, 29}, // ff91 - {0.073730f, 0.815430f, 0.082031f, 0.829590f, -0.6875f, -27.5000f, 15.0000f, 17, 29}, // ff92 - {0.666504f, 0.822266f, 0.674805f, 0.835449f, -0.7500f, -26.1875f, 15.0000f, 17, 27}, // ff93 - {0.577637f, 0.811035f, 0.585938f, 0.825684f, -0.6250f, -27.9375f, 15.0000f, 17, 30}, // ff94 - {0.675293f, 0.822266f, 0.683594f, 0.835449f, -0.7500f, -25.9375f, 15.0000f, 17, 27}, // ff95 - {0.118164f, 0.826172f, 0.125977f, 0.839355f, -0.1875f, -25.9375f, 15.0000f, 16, 27}, // ff96 - {0.218750f, 0.822266f, 0.226563f, 0.836426f, -0.3125f, -26.5000f, 15.0000f, 16, 29}, // ff97 - {0.110840f, 0.836426f, 0.117188f, 0.850586f, 1.1250f, -27.0625f, 15.0000f, 13, 29}, // ff98 - {0.889160f, 0.798828f, 0.897949f, 0.813477f, -1.5000f, -27.6875f, 15.0000f, 18, 30}, // ff99 - {0.237793f, 0.822266f, 0.245117f, 0.836426f, 1.3125f, -27.6875f, 15.0000f, 15, 29}, // ff9a - {0.992188f, 0.291016f, 0.999512f, 0.304199f, 0.0625f, -25.9375f, 15.0000f, 15, 27}, // ff9b - {0.778809f, 0.822754f, 0.786621f, 0.836426f, -0.1250f, -25.9375f, 15.0000f, 16, 28}, // ff9c - {0.509277f, 0.818359f, 0.517578f, 0.832031f, -0.8125f, -26.5000f, 15.0000f, 17, 28}, // ff9d - {0.816895f, 0.522461f, 0.822266f, 0.527832f, -1.3750f, -26.5000f, 15.0000f, 11, 11}, // ff9e - {0.781250f, 0.554688f, 0.786133f, 0.559570f, -0.8750f, -27.1875f, 15.0000f, 10, 10}, // ff9f +// RANGE: 0xff00 - 0xfff0, start 0x8340 + {0.027344f, 0.800293f, 0.040527f, 0.813477f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff00 + {0.205566f, 0.237793f, 0.209473f, 0.250488f, 11.3125f, -25.5000f, 30.0000f, 8, 26}, // ff01 + {0.827637f, 0.145508f, 0.833984f, 0.151367f, 8.8750f, -25.5000f, 30.0000f, 13, 12}, // ff02 + {0.890625f, 0.857910f, 0.900879f, 0.871094f, 5.0000f, -25.8750f, 30.0000f, 21, 27}, // ff03 + {0.716797f, 0.847168f, 0.726074f, 0.862305f, 5.8125f, -27.5000f, 30.0000f, 19, 31}, // ff04 + {0.381348f, 0.800293f, 0.394531f, 0.813477f, 1.8125f, -25.8750f, 30.0000f, 27, 27}, // ff05 + {0.243164f, 0.835449f, 0.254395f, 0.848633f, 3.9375f, -25.8750f, 30.0000f, 23, 27}, // ff06 + {0.398438f, 0.294922f, 0.402344f, 0.300781f, 11.3750f, -25.5000f, 30.0000f, 8, 12}, // ff07 + {0.971191f, 0.018555f, 0.977051f, 0.034668f, 9.4375f, -25.8750f, 30.0000f, 12, 33}, // ff08 + {0.189453f, 0.909668f, 0.195313f, 0.925781f, 9.4375f, -25.8750f, 30.0000f, 12, 33}, // ff09 + {0.869141f, 0.048828f, 0.875977f, 0.055664f, 8.1250f, -25.8750f, 30.0000f, 14, 14}, // ff0a + {0.167480f, 0.051758f, 0.176758f, 0.061035f, 5.8750f, -21.7500f, 30.0000f, 19, 19}, // ff0b + {0.524902f, 0.329590f, 0.528809f, 0.335449f, 11.3750f, -7.0625f, 30.0000f, 8, 12}, // ff0c + {0.652344f, 0.231934f, 0.658691f, 0.235352f, 9.0000f, -13.1250f, 30.0000f, 13, 7}, // ff0d + {0.292969f, 0.510742f, 0.296875f, 0.514648f, 11.4375f, -7.0625f, 30.0000f, 8, 8}, // ff0e + {0.866211f, 0.725586f, 0.872559f, 0.738770f, 8.8125f, -25.5000f, 30.0000f, 13, 27}, // ff0f + {0.180176f, 0.890137f, 0.189453f, 0.902832f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff10 + {0.097168f, 0.819824f, 0.103027f, 0.832520f, 9.0000f, -25.6250f, 30.0000f, 12, 26}, // ff11 + {0.723145f, 0.890137f, 0.732422f, 0.902832f, 5.8750f, -25.5625f, 30.0000f, 19, 26}, // ff12 + {0.312012f, 0.890625f, 0.321289f, 0.903320f, 6.0000f, -25.5625f, 30.0000f, 19, 26}, // ff13 + {0.426270f, 0.890625f, 0.435547f, 0.903320f, 5.5625f, -25.5000f, 30.0000f, 19, 26}, // ff14 + {0.593262f, 0.890625f, 0.602539f, 0.903320f, 5.8750f, -25.1875f, 30.0000f, 19, 26}, // ff15 + {0.683594f, 0.890625f, 0.692871f, 0.903320f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff16 + {0.337891f, 0.899414f, 0.346680f, 0.912109f, 6.0000f, -25.1875f, 30.0000f, 18, 26}, // ff17 + {0.705566f, 0.890625f, 0.714844f, 0.903320f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff18 + {0.893066f, 0.890625f, 0.902344f, 0.903320f, 5.9375f, -25.5625f, 30.0000f, 19, 26}, // ff19 + {0.350098f, 0.280273f, 0.354004f, 0.290039f, 11.4375f, -19.5625f, 30.0000f, 8, 20}, // ff1a + {0.859863f, 0.153320f, 0.863770f, 0.165039f, 11.4375f, -19.5625f, 30.0000f, 8, 24}, // ff1b + {0.552734f, 0.097168f, 0.562012f, 0.106445f, 5.8750f, -21.8750f, 30.0000f, 19, 19}, // ff1c + {0.854980f, 0.064941f, 0.864258f, 0.071777f, 5.8750f, -19.1250f, 30.0000f, 19, 14}, // ff1d + {0.538086f, 0.161621f, 0.547363f, 0.170898f, 5.8750f, -21.8750f, 30.0000f, 19, 19}, // ff1e + {0.551270f, 0.899414f, 0.560059f, 0.912109f, 6.0625f, -25.8750f, 30.0000f, 18, 26}, // ff1f + {0.615234f, 0.051270f, 0.630859f, 0.067383f, -0.9375f, -25.8750f, 30.0000f, 32, 33}, // ff20 + {0.734375f, 0.823242f, 0.746582f, 0.835938f, 2.9375f, -25.5000f, 30.0000f, 25, 26}, // ff21 + {0.212891f, 0.865723f, 0.223145f, 0.878418f, 4.8125f, -25.5000f, 30.0000f, 21, 26}, // ff22 + {0.763184f, 0.835449f, 0.774414f, 0.848633f, 3.5000f, -25.8750f, 30.0000f, 23, 27}, // ff23 + {0.424805f, 0.853516f, 0.435547f, 0.866211f, 4.0625f, -25.5000f, 30.0000f, 22, 26}, // ff24 + {0.283203f, 0.865723f, 0.293457f, 0.878418f, 4.9375f, -25.5000f, 30.0000f, 21, 26}, // ff25 + {0.932129f, 0.890625f, 0.941406f, 0.903320f, 5.6875f, -25.5000f, 30.0000f, 19, 26}, // ff26 + {0.468750f, 0.825195f, 0.480469f, 0.838379f, 3.0625f, -25.8750f, 30.0000f, 24, 27}, // ff27 + {0.637207f, 0.866211f, 0.647461f, 0.878906f, 4.5625f, -25.5000f, 30.0000f, 21, 26}, // ff28 + {0.952148f, 0.244629f, 0.955566f, 0.257324f, 11.5625f, -25.5000f, 30.0000f, 7, 26}, // ff29 + {0.733398f, 0.659668f, 0.741211f, 0.672363f, 7.1250f, -25.5000f, 30.0000f, 16, 26}, // ff2a + {0.466797f, 0.853516f, 0.477539f, 0.866211f, 4.0625f, -25.5000f, 30.0000f, 22, 26}, // ff2b + {0.560547f, 0.899902f, 0.569336f, 0.912598f, 6.2500f, -25.5000f, 30.0000f, 18, 26}, // ff2c + {0.357422f, 0.824219f, 0.369629f, 0.836914f, 2.7500f, -25.5000f, 30.0000f, 25, 26}, // ff2d + {0.837891f, 0.866211f, 0.848145f, 0.878906f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff2e + {0.586914f, 0.817871f, 0.599121f, 0.831055f, 2.6875f, -25.8750f, 30.0000f, 25, 27}, // ff2f + {0.420898f, 0.866699f, 0.431152f, 0.879395f, 4.7500f, -25.5000f, 30.0000f, 21, 26}, // ff30 + {0.502441f, 0.811035f, 0.514648f, 0.824707f, 2.5000f, -25.8750f, 30.0000f, 25, 28}, // ff31 + {0.895020f, 0.844727f, 0.906250f, 0.857422f, 3.5000f, -25.5000f, 30.0000f, 23, 26}, // ff32 + {0.196289f, 0.846191f, 0.207031f, 0.859375f, 4.4375f, -25.8750f, 30.0000f, 22, 27}, // ff33 + {0.490723f, 0.854004f, 0.501465f, 0.866699f, 4.4375f, -25.5000f, 30.0000f, 22, 26}, // ff34 + {0.462402f, 0.866699f, 0.472656f, 0.879395f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff35 + {0.265625f, 0.833984f, 0.277344f, 0.846680f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff36 + {0.374512f, 0.706055f, 0.390137f, 0.718750f, -0.8750f, -25.5000f, 30.0000f, 32, 26}, // ff37 + {0.694824f, 0.833984f, 0.706543f, 0.846680f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff38 + {0.031250f, 0.834473f, 0.042969f, 0.847168f, 3.1250f, -25.5000f, 30.0000f, 24, 26}, // ff39 + {0.223633f, 0.867188f, 0.233887f, 0.879883f, 4.5000f, -25.5000f, 30.0000f, 21, 26}, // ff3a + {0.631348f, 0.918457f, 0.636230f, 0.934082f, 10.0625f, -25.5000f, 30.0000f, 10, 32}, // ff3b + {0.833496f, 0.729492f, 0.839844f, 0.742676f, 8.8125f, -25.5000f, 30.0000f, 13, 27}, // ff3c + {0.469727f, 0.918945f, 0.474609f, 0.934570f, 10.0625f, -25.5000f, 30.0000f, 10, 32}, // ff3d + {0.746094f, 0.230957f, 0.754395f, 0.238770f, 6.6875f, -25.5000f, 30.0000f, 17, 16}, // ff3e + {0.423828f, 0.067871f, 0.433594f, 0.070801f, 5.3125f, -1.7500f, 30.0000f, 20, 6}, // ff3f + {0.517578f, 0.412598f, 0.522461f, 0.416992f, 10.2500f, -25.8750f, 30.0000f, 10, 9}, // ff40 + {0.713379f, 0.911133f, 0.722656f, 0.921387f, 5.8125f, -19.9375f, 30.0000f, 19, 21}, // ff41 + {0.639160f, 0.899902f, 0.647949f, 0.912598f, 6.1875f, -25.5000f, 30.0000f, 18, 26}, // ff42 + {0.813965f, 0.916016f, 0.822754f, 0.926270f, 6.1875f, -19.9375f, 30.0000f, 18, 21}, // ff43 + {0.007813f, 0.901367f, 0.016602f, 0.914063f, 6.1875f, -25.5000f, 30.0000f, 18, 26}, // ff44 + {0.769531f, 0.912109f, 0.778809f, 0.922363f, 5.8125f, -19.9375f, 30.0000f, 19, 21}, // ff45 + {0.748535f, 0.672363f, 0.755371f, 0.685059f, 8.4375f, -25.8750f, 30.0000f, 14, 26}, // ff46 + {0.960449f, 0.891602f, 0.969238f, 0.904785f, 6.1250f, -19.9375f, 30.0000f, 18, 27}, // ff47 + {0.648438f, 0.903809f, 0.656738f, 0.916504f, 6.6250f, -25.5000f, 30.0000f, 17, 26}, // ff48 + {0.253906f, 0.255859f, 0.257324f, 0.268555f, 11.6250f, -25.5000f, 30.0000f, 7, 26}, // ff49 + {0.504883f, 0.918945f, 0.509766f, 0.934570f, 10.0000f, -25.5000f, 30.0000f, 10, 32}, // ff4a + {0.683594f, 0.903809f, 0.691895f, 0.916504f, 6.5000f, -25.5000f, 30.0000f, 17, 26}, // ff4b + {0.785645f, 0.328613f, 0.789063f, 0.341309f, 11.6250f, -25.5000f, 30.0000f, 7, 26}, // ff4c + {0.409668f, 0.480957f, 0.422363f, 0.490723f, 2.4375f, -19.9375f, 30.0000f, 26, 20}, // ff4d + {0.656250f, 0.918457f, 0.664551f, 0.928223f, 6.6250f, -19.9375f, 30.0000f, 17, 20}, // ff4e + {0.793945f, 0.912109f, 0.803223f, 0.922363f, 5.6875f, -19.9375f, 30.0000f, 19, 21}, // ff4f + {0.264648f, 0.901367f, 0.273438f, 0.914063f, 6.1875f, -19.9375f, 30.0000f, 18, 26}, // ff50 + {0.347168f, 0.901367f, 0.355957f, 0.914063f, 6.1875f, -19.9375f, 30.0000f, 18, 26}, // ff51 + {0.608887f, 0.058105f, 0.615234f, 0.067871f, 8.7500f, -19.9375f, 30.0000f, 13, 20}, // ff52 + {0.364258f, 0.917969f, 0.372559f, 0.928223f, 6.5625f, -19.9375f, 30.0000f, 17, 21}, // ff53 + {0.237305f, 0.836426f, 0.243164f, 0.849121f, 9.1875f, -25.0000f, 30.0000f, 12, 26}, // ff54 + {0.270508f, 0.918945f, 0.278809f, 0.928711f, 6.6250f, -19.5625f, 30.0000f, 17, 20}, // ff55 + {0.450684f, 0.916016f, 0.459961f, 0.925781f, 5.8125f, -19.5625f, 30.0000f, 19, 20}, // ff56 + {0.108887f, 0.520996f, 0.121582f, 0.530762f, 2.3125f, -19.5625f, 30.0000f, 26, 20}, // ff57 + {0.486328f, 0.916016f, 0.495605f, 0.925781f, 5.6875f, -19.5625f, 30.0000f, 19, 20}, // ff58 + {0.450684f, 0.891113f, 0.459961f, 0.903809f, 5.8125f, -19.5625f, 30.0000f, 19, 26}, // ff59 + {0.613281f, 0.917480f, 0.622070f, 0.927246f, 6.0625f, -19.5625f, 30.0000f, 18, 20}, // ff5a + {0.993164f, 0.067871f, 0.999512f, 0.083984f, 8.7500f, -25.8750f, 30.0000f, 13, 33}, // ff5b + {0.699219f, 0.584961f, 0.702637f, 0.600586f, 11.8750f, -25.5000f, 30.0000f, 7, 32}, // ff5c + {0.407227f, 0.902832f, 0.413574f, 0.918945f, 8.7500f, -25.8750f, 30.0000f, 13, 33}, // ff5d + {0.224609f, 0.282227f, 0.233887f, 0.286621f, 5.5000f, -17.0000f, 30.0000f, 19, 9}, // ff5e + {0.775879f, 0.800293f, 0.789063f, 0.813477f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff5f + {0.174316f, 0.800781f, 0.187500f, 0.813965f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ff60 + {0.994141f, 0.359863f, 0.999023f, 0.364746f, -0.4375f, -8.2500f, 15.0000f, 10, 10}, // ff61 + {0.028320f, 0.892090f, 0.035645f, 0.907715f, 0.3125f, -29.1250f, 15.0000f, 15, 32}, // ff62 + {0.292480f, 0.892090f, 0.299805f, 0.907715f, 0.3125f, -29.1250f, 15.0000f, 15, 32}, // ff63 + {0.773926f, 0.288574f, 0.779785f, 0.294434f, -0.3750f, -9.1875f, 15.0000f, 12, 12}, // ff64 + {0.709473f, 0.511719f, 0.713379f, 0.515625f, 3.8125f, -17.1875f, 15.0000f, 8, 8}, // ff65 + {0.356445f, 0.901367f, 0.364258f, 0.915527f, -0.0625f, -26.6250f, 15.0000f, 16, 29}, // ff66 + {0.705566f, 0.705078f, 0.713379f, 0.718262f, -0.1250f, -26.0000f, 15.0000f, 16, 27}, // ff67 + {0.776855f, 0.700195f, 0.784668f, 0.713867f, -0.6875f, -27.1250f, 15.0000f, 16, 28}, // ff68 + {0.577637f, 0.906250f, 0.584961f, 0.919922f, 0.3125f, -26.9375f, 15.0000f, 15, 28}, // ff69 + {0.910645f, 0.024414f, 0.918457f, 0.036133f, -0.1875f, -24.6875f, 15.0000f, 16, 24}, // ff6a + {0.844238f, 0.893555f, 0.852539f, 0.907227f, -0.8750f, -26.5625f, 15.0000f, 17, 28}, // ff6b + {0.902832f, 0.893555f, 0.911133f, 0.907227f, -0.5000f, -26.6875f, 15.0000f, 17, 28}, // ff6c + {0.901367f, 0.056641f, 0.909180f, 0.068359f, -0.1875f, -24.8750f, 15.0000f, 16, 24}, // ff6d + {0.498535f, 0.164551f, 0.505859f, 0.176758f, 0.3125f, -25.0625f, 15.0000f, 15, 25}, // ff6e + {0.987305f, 0.907715f, 0.995117f, 0.920410f, -0.3750f, -25.8125f, 15.0000f, 16, 26}, // ff6f + {0.771973f, 0.156250f, 0.779297f, 0.159668f, 0.3750f, -16.3750f, 15.0000f, 15, 7}, // ff70 + {0.105957f, 0.877441f, 0.114746f, 0.891602f, -0.7500f, -26.5625f, 15.0000f, 18, 29}, // ff71 + {0.884277f, 0.886719f, 0.892578f, 0.901367f, -0.8125f, -27.8750f, 15.0000f, 17, 30}, // ff72 + {0.762695f, 0.685547f, 0.770508f, 0.700195f, -0.1875f, -28.1250f, 15.0000f, 16, 30}, // ff73 + {0.112305f, 0.902832f, 0.120605f, 0.916016f, -0.7500f, -26.0625f, 15.0000f, 17, 27}, // ff74 + {0.125977f, 0.887207f, 0.134277f, 0.901855f, -1.0000f, -27.6875f, 15.0000f, 17, 30}, // ff75 + {0.115234f, 0.887695f, 0.123535f, 0.902344f, -0.8750f, -27.8750f, 15.0000f, 17, 30}, // ff76 + {0.303223f, 0.887695f, 0.311523f, 0.902344f, -0.7500f, -28.0000f, 15.0000f, 17, 30}, // ff77 + {0.844238f, 0.742676f, 0.852051f, 0.757324f, -0.8125f, -28.4375f, 15.0000f, 16, 30}, // ff78 + {0.387207f, 0.887695f, 0.395508f, 0.902344f, -0.8750f, -28.4375f, 15.0000f, 17, 30}, // ff79 + {0.942383f, 0.905762f, 0.950195f, 0.918945f, -0.2500f, -26.0625f, 15.0000f, 16, 27}, // ff7a + {0.395996f, 0.887695f, 0.404297f, 0.902344f, -0.7500f, -27.6875f, 15.0000f, 17, 30}, // ff7b + {0.243652f, 0.891602f, 0.251953f, 0.905762f, -0.9375f, -27.1250f, 15.0000f, 17, 29}, // ff7c + {0.765137f, 0.887695f, 0.773926f, 0.901367f, -1.1875f, -25.8125f, 15.0000f, 18, 28}, // ff7d + {0.950684f, 0.893555f, 0.958984f, 0.907227f, -0.6875f, -27.6250f, 15.0000f, 17, 28}, // ff7e + {0.374023f, 0.901367f, 0.381836f, 0.915527f, -0.5625f, -27.4375f, 15.0000f, 16, 29}, // ff7f + {0.404785f, 0.887695f, 0.413086f, 0.902344f, -0.9375f, -27.9375f, 15.0000f, 17, 30}, // ff80 + {0.441895f, 0.887695f, 0.450195f, 0.902344f, -0.7500f, -27.9375f, 15.0000f, 17, 30}, // ff81 + {0.572266f, 0.891602f, 0.580566f, 0.905762f, -0.6875f, -27.1250f, 15.0000f, 17, 29}, // ff82 + {0.581055f, 0.891602f, 0.589355f, 0.905762f, -0.7500f, -26.2500f, 15.0000f, 17, 29}, // ff83 + {0.875977f, 0.165039f, 0.882813f, 0.179199f, 1.6250f, -27.6250f, 15.0000f, 14, 29}, // ff84 + {0.507324f, 0.887695f, 0.515625f, 0.902344f, -0.7500f, -27.6250f, 15.0000f, 17, 30}, // ff85 + {0.883301f, 0.560547f, 0.891602f, 0.572754f, -0.7500f, -25.3750f, 15.0000f, 17, 25}, // ff86 + {0.065430f, 0.894043f, 0.073730f, 0.907715f, -0.7500f, -26.0625f, 15.0000f, 17, 28}, // ff87 + {0.137207f, 0.877441f, 0.145996f, 0.891602f, -1.2500f, -27.0625f, 15.0000f, 18, 29}, // ff88 + {0.382324f, 0.902832f, 0.390137f, 0.916504f, -0.5000f, -26.2500f, 15.0000f, 16, 28}, // ff89 + {0.603027f, 0.891602f, 0.611328f, 0.905762f, -1.0000f, -27.7500f, 15.0000f, 17, 29}, // ff8a + {0.390625f, 0.902832f, 0.398438f, 0.916504f, 0.8125f, -27.1250f, 15.0000f, 16, 28}, // ff8b + {0.398926f, 0.902832f, 0.406738f, 0.916504f, -0.0625f, -26.0000f, 15.0000f, 16, 28}, // ff8c + {0.847656f, 0.908691f, 0.856445f, 0.919922f, -1.2500f, -23.3750f, 15.0000f, 18, 23}, // ff8d + {0.256836f, 0.877441f, 0.265625f, 0.891602f, -1.3750f, -27.5625f, 15.0000f, 18, 29}, // ff8e + {0.132813f, 0.902832f, 0.141113f, 0.916016f, -0.5625f, -25.8750f, 15.0000f, 17, 27}, // ff8f + {0.611816f, 0.891602f, 0.620117f, 0.905762f, -0.8750f, -27.1250f, 15.0000f, 17, 29}, // ff90 + {0.293945f, 0.877441f, 0.302734f, 0.891602f, -1.1875f, -27.7500f, 15.0000f, 18, 29}, // ff91 + {0.620605f, 0.891602f, 0.628906f, 0.905762f, -0.6875f, -27.5000f, 15.0000f, 17, 29}, // ff92 + {0.155273f, 0.902832f, 0.163574f, 0.916016f, -0.7500f, -26.1875f, 15.0000f, 17, 27}, // ff93 + {0.542480f, 0.887695f, 0.550781f, 0.902344f, -0.6250f, -27.9375f, 15.0000f, 17, 30}, // ff94 + {0.196289f, 0.902832f, 0.204590f, 0.916016f, -0.7500f, -25.9375f, 15.0000f, 17, 27}, // ff95 + {0.044922f, 0.906250f, 0.052734f, 0.919434f, -0.1875f, -25.9375f, 15.0000f, 16, 27}, // ff96 + {0.489746f, 0.901367f, 0.497559f, 0.915527f, -0.3125f, -26.5000f, 15.0000f, 16, 29}, // ff97 + {0.867188f, 0.292480f, 0.873535f, 0.306641f, 1.1250f, -27.0625f, 15.0000f, 13, 29}, // ff98 + {0.161133f, 0.874512f, 0.169922f, 0.889160f, -1.5000f, -27.6875f, 15.0000f, 18, 30}, // ff99 + {0.750488f, 0.905762f, 0.757813f, 0.919922f, 1.3125f, -27.6875f, 15.0000f, 15, 29}, // ff9a + {0.465820f, 0.054688f, 0.473145f, 0.067871f, 0.0625f, -25.9375f, 15.0000f, 15, 27}, // ff9b + {0.442383f, 0.902832f, 0.450195f, 0.916504f, -0.1250f, -25.9375f, 15.0000f, 16, 28}, // ff9c + {0.205566f, 0.894043f, 0.213867f, 0.907715f, -0.8125f, -26.5000f, 15.0000f, 17, 28}, // ff9d + {0.537598f, 0.313477f, 0.542969f, 0.318848f, -1.3750f, -26.5000f, 15.0000f, 11, 11}, // ff9e + {0.994141f, 0.365234f, 0.999023f, 0.370117f, -0.8750f, -27.1875f, 15.0000f, 10, 10}, // ff9f {0.000000f, 0.000000f, 0.000488f, 0.000488f, -2.0000f, -4.0000f, 15.0000f, 1, 1}, // ffa0 - {0.518555f, 0.836914f, 0.526855f, 0.847656f, -0.5625f, -23.9375f, 15.0000f, 17, 22}, // ffa1 - {0.593262f, 0.834961f, 0.602051f, 0.845703f, -1.1250f, -23.9375f, 15.0000f, 18, 22}, // ffa2 - {0.884277f, 0.828613f, 0.893555f, 0.839355f, -1.4375f, -23.9375f, 15.0000f, 19, 22}, // ffa3 - {0.774414f, 0.836914f, 0.782715f, 0.847656f, -0.5625f, -24.0000f, 15.0000f, 17, 22}, // ffa4 - {0.613281f, 0.834961f, 0.622070f, 0.845703f, -1.1250f, -24.0000f, 15.0000f, 18, 22}, // ffa5 - {0.796875f, 0.834961f, 0.805664f, 0.845703f, -1.1250f, -24.0000f, 15.0000f, 18, 22}, // ffa6 - {0.569824f, 0.840332f, 0.577637f, 0.851074f, -0.3750f, -23.9375f, 15.0000f, 16, 22}, // ffa7 - {0.817871f, 0.834961f, 0.826660f, 0.845703f, -1.1875f, -23.9375f, 15.0000f, 18, 22}, // ffa8 - {0.270508f, 0.840820f, 0.278320f, 0.851563f, -0.2500f, -23.9375f, 15.0000f, 16, 22}, // ffa9 - {0.875000f, 0.836914f, 0.883301f, 0.847656f, -0.7500f, -23.9375f, 15.0000f, 17, 22}, // ffaa - {0.939453f, 0.836914f, 0.947754f, 0.847656f, -0.8750f, -23.9375f, 15.0000f, 17, 22}, // ffab - {0.948242f, 0.836914f, 0.956543f, 0.847656f, -0.8125f, -23.9375f, 15.0000f, 17, 22}, // ffac - {0.856934f, 0.834961f, 0.865723f, 0.845703f, -0.8125f, -23.9375f, 15.0000f, 18, 22}, // ffad - {0.157227f, 0.837402f, 0.165527f, 0.848145f, -0.7500f, -24.0000f, 15.0000f, 17, 22}, // ffae - {0.372559f, 0.837402f, 0.380859f, 0.848145f, -1.0000f, -24.0000f, 15.0000f, 17, 22}, // ffaf - {0.930176f, 0.834961f, 0.938965f, 0.845703f, -1.0625f, -24.0000f, 15.0000f, 18, 22}, // ffb0 - {0.505859f, 0.690430f, 0.513184f, 0.701172f, 0.3750f, -23.9375f, 15.0000f, 15, 22}, // ffb1 - {0.718750f, 0.748047f, 0.726074f, 0.758789f, 0.3750f, -24.0000f, 15.0000f, 15, 22}, // ffb2 - {0.544922f, 0.837402f, 0.553223f, 0.848145f, -0.8750f, -23.9375f, 15.0000f, 17, 22}, // ffb3 - {0.971191f, 0.834961f, 0.979980f, 0.845703f, -0.8750f, -23.9375f, 15.0000f, 18, 22}, // ffb4 - {0.059082f, 0.829102f, 0.068359f, 0.839844f, -1.6250f, -23.8750f, 15.0000f, 19, 22}, // ffb5 - {0.091309f, 0.829102f, 0.100586f, 0.839844f, -2.0000f, -23.9375f, 15.0000f, 19, 22}, // ffb6 - {0.578125f, 0.841309f, 0.585938f, 0.852051f, -0.4375f, -24.0000f, 15.0000f, 16, 22}, // ffb7 - {0.198730f, 0.835449f, 0.207520f, 0.846191f, -1.5000f, -23.9375f, 15.0000f, 18, 22}, // ffb8 - {0.182129f, 0.829102f, 0.191406f, 0.839844f, -1.6875f, -24.0000f, 15.0000f, 19, 22}, // ffb9 - {0.033203f, 0.835938f, 0.041992f, 0.846680f, -1.4375f, -23.9375f, 15.0000f, 18, 22}, // ffba - {0.074707f, 0.789551f, 0.082031f, 0.800293f, 0.1250f, -23.9375f, 15.0000f, 15, 22}, // ffbb - {0.989746f, 0.841309f, 0.997559f, 0.852051f, -0.3125f, -23.9375f, 15.0000f, 16, 22}, // ffbc - {0.324707f, 0.841797f, 0.332520f, 0.852539f, -0.1875f, -23.9375f, 15.0000f, 16, 22}, // ffbd - {0.561035f, 0.837891f, 0.569336f, 0.848633f, -0.6875f, -23.9375f, 15.0000f, 17, 22}, // ffbe - {0.852051f, 0.738770f, 0.865234f, 0.751953f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffbf - {0.027344f, 0.739746f, 0.040527f, 0.752930f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc0 - {0.149902f, 0.739746f, 0.163086f, 0.752930f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc1 - {0.838379f, 0.829590f, 0.844727f, 0.845215f, 1.1250f, -29.2500f, 15.0000f, 13, 32}, // ffc2 - {0.930664f, 0.256836f, 0.937500f, 0.272461f, 0.8125f, -29.2500f, 15.0000f, 14, 32}, // ffc3 - {0.894043f, 0.829590f, 0.900391f, 0.845215f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffc4 - {0.495117f, 0.821289f, 0.501953f, 0.836914f, 0.6875f, -29.2500f, 15.0000f, 14, 32}, // ffc5 - {0.026367f, 0.830078f, 0.032715f, 0.845703f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffc6 - {0.743164f, 0.791992f, 0.751465f, 0.807617f, -0.8125f, -29.3125f, 15.0000f, 17, 32}, // ffc7 - {0.393066f, 0.741699f, 0.406250f, 0.754883f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc8 - {0.406738f, 0.741699f, 0.419922f, 0.754883f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc9 - {0.068848f, 0.830078f, 0.075195f, 0.845703f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffca - {0.045410f, 0.793945f, 0.053711f, 0.809570f, -0.8125f, -29.3125f, 15.0000f, 17, 32}, // ffcb - {0.427734f, 0.079590f, 0.436035f, 0.087891f, -0.6875f, -22.4375f, 15.0000f, 17, 17}, // ffcc - {0.571777f, 0.780273f, 0.580566f, 0.795898f, -1.3125f, -29.2500f, 15.0000f, 18, 32}, // ffcd - {0.984863f, 0.780273f, 0.993652f, 0.795898f, -1.1875f, -29.2500f, 15.0000f, 18, 32}, // ffce - {0.269531f, 0.793945f, 0.277832f, 0.809570f, -1.3125f, -29.2500f, 15.0000f, 17, 32}, // ffcf - {0.649414f, 0.742188f, 0.662598f, 0.755371f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd0 - {0.062500f, 0.743164f, 0.075684f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd1 - {0.347168f, 0.049805f, 0.355957f, 0.058105f, -1.1250f, -22.4375f, 15.0000f, 18, 17}, // ffd2 - {0.756348f, 0.842773f, 0.764648f, 0.852051f, -0.8125f, -20.6875f, 15.0000f, 17, 19}, // ffd3 - {0.122559f, 0.794922f, 0.130859f, 0.810547f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffd4 - {0.917480f, 0.781250f, 0.926270f, 0.796875f, -1.2500f, -29.3125f, 15.0000f, 18, 32}, // ffd5 - {0.813965f, 0.795410f, 0.822266f, 0.811035f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffd6 - {0.783203f, 0.842773f, 0.791504f, 0.852051f, -0.8125f, -21.6250f, 15.0000f, 17, 19}, // ffd7 - {0.076172f, 0.743164f, 0.089355f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd8 - {0.089844f, 0.743164f, 0.103027f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd9 - {0.675293f, 0.191895f, 0.684082f, 0.195313f, -1.1875f, -17.0625f, 15.0000f, 18, 7}, // ffda - {0.421875f, 0.795898f, 0.430176f, 0.811523f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffdb - {0.777832f, 0.569336f, 0.781250f, 0.584961f, 4.3750f, -29.2500f, 15.0000f, 7, 32}, // ffdc - {0.103516f, 0.743164f, 0.116699f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffdd - {0.196777f, 0.743164f, 0.209961f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffde - {0.756836f, 0.743164f, 0.770020f, 0.756348f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffdf - {0.182617f, 0.781738f, 0.191406f, 0.797363f, 6.1875f, -25.5000f, 30.0000f, 18, 32}, // ffe0 - {0.962402f, 0.798828f, 0.972168f, 0.812012f, 5.2500f, -25.8750f, 30.0000f, 20, 27}, // ffe1 - {0.337891f, 0.236816f, 0.347168f, 0.243652f, 5.8750f, -19.1250f, 30.0000f, 19, 14}, // ffe2 - {0.700684f, 0.111816f, 0.710449f, 0.114746f, 5.3125f, -29.3125f, 30.0000f, 20, 6}, // ffe3 - {0.874512f, 0.572266f, 0.877930f, 0.587891f, 11.8750f, -25.5000f, 30.0000f, 7, 32}, // ffe4 - {0.111816f, 0.794922f, 0.122070f, 0.807617f, 4.6875f, -25.5000f, 30.0000f, 21, 26}, // ffe5 - {0.620117f, 0.674805f, 0.635742f, 0.687500f, -0.8750f, -25.5000f, 30.0000f, 32, 26}, // ffe6 - {0.464355f, 0.743652f, 0.477539f, 0.756836f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffe7 - {0.712402f, 0.832520f, 0.715820f, 0.852539f, 4.1875f, -33.8125f, 15.0000f, 7, 41}, // ffe8 - {0.898438f, 0.715332f, 0.906738f, 0.722168f, -0.8125f, -16.3750f, 15.0000f, 17, 14}, // ffe9 - {0.180176f, 0.699707f, 0.187012f, 0.708008f, 0.7500f, -16.6250f, 15.0000f, 14, 17}, // ffea - {0.464355f, 0.735840f, 0.472656f, 0.742676f, -0.8125f, -16.3750f, 15.0000f, 17, 14}, // ffeb - {0.369629f, 0.750000f, 0.376465f, 0.758301f, 0.7500f, -16.6250f, 15.0000f, 14, 17}, // ffec - {0.334961f, 0.082031f, 0.343262f, 0.090332f, -1.0000f, -21.7500f, 15.0000f, 17, 17}, // ffed - {0.415527f, 0.111816f, 0.423828f, 0.120117f, -0.9375f, -21.6875f, 15.0000f, 17, 17}, // ffee - {0.558594f, 0.743652f, 0.571777f, 0.756836f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffef + {0.515137f, 0.916504f, 0.523438f, 0.927246f, -0.5625f, -23.9375f, 15.0000f, 17, 22}, // ffa1 + {0.758301f, 0.913086f, 0.767090f, 0.923828f, -1.1250f, -23.9375f, 15.0000f, 18, 22}, // ffa2 + {0.627930f, 0.907227f, 0.637207f, 0.917969f, -1.4375f, -23.9375f, 15.0000f, 19, 22}, // ffa3 + {0.723145f, 0.916504f, 0.731445f, 0.927246f, -0.5625f, -24.0000f, 15.0000f, 17, 22}, // ffa4 + {0.006836f, 0.914551f, 0.015625f, 0.925293f, -1.1250f, -24.0000f, 15.0000f, 18, 22}, // ffa5 + {0.261230f, 0.914551f, 0.270020f, 0.925293f, -1.1250f, -24.0000f, 15.0000f, 18, 22}, // ffa6 + {0.643066f, 0.205078f, 0.650879f, 0.215820f, -0.3750f, -23.9375f, 15.0000f, 16, 22}, // ffa7 + {0.345215f, 0.914551f, 0.354004f, 0.925293f, -1.1875f, -23.9375f, 15.0000f, 18, 22}, // ffa8 + {0.722656f, 0.235352f, 0.730469f, 0.246094f, -0.2500f, -23.9375f, 15.0000f, 16, 22}, // ffa9 + {0.731934f, 0.916504f, 0.740234f, 0.927246f, -0.7500f, -23.9375f, 15.0000f, 17, 22}, // ffaa + {0.053223f, 0.916992f, 0.061523f, 0.927734f, -0.8750f, -23.9375f, 15.0000f, 17, 22}, // ffab + {0.099121f, 0.916992f, 0.107422f, 0.927734f, -0.8125f, -23.9375f, 15.0000f, 17, 22}, // ffac + {0.703125f, 0.914551f, 0.711914f, 0.925293f, -0.8125f, -23.9375f, 15.0000f, 18, 22}, // ffad + {0.308105f, 0.916992f, 0.316406f, 0.927734f, -0.7500f, -24.0000f, 15.0000f, 17, 22}, // ffae + {0.382324f, 0.916992f, 0.390625f, 0.927734f, -1.0000f, -24.0000f, 15.0000f, 17, 22}, // ffaf + {0.892578f, 0.914551f, 0.901367f, 0.925293f, -1.0625f, -24.0000f, 15.0000f, 18, 22}, // ffb0 + {0.675293f, 0.108398f, 0.682617f, 0.119141f, 0.3750f, -23.9375f, 15.0000f, 15, 22}, // ffb1 + {0.385742f, 0.136719f, 0.393066f, 0.147461f, 0.3750f, -24.0000f, 15.0000f, 15, 22}, // ffb2 + {0.391113f, 0.916992f, 0.399414f, 0.927734f, -0.8750f, -23.9375f, 15.0000f, 17, 22}, // ffb3 + {0.779297f, 0.915039f, 0.788086f, 0.925781f, -0.8750f, -23.9375f, 15.0000f, 18, 22}, // ffb4 + {0.273926f, 0.907715f, 0.283203f, 0.918457f, -1.6250f, -23.8750f, 15.0000f, 19, 22}, // ffb5 + {0.804199f, 0.907715f, 0.813477f, 0.918457f, -2.0000f, -23.9375f, 15.0000f, 19, 22}, // ffb6 + {0.818848f, 0.265137f, 0.826660f, 0.275879f, -0.4375f, -24.0000f, 15.0000f, 16, 22}, // ffb7 + {0.034668f, 0.915527f, 0.043457f, 0.926270f, -1.5000f, -23.9375f, 15.0000f, 18, 22}, // ffb8 + {0.831055f, 0.907715f, 0.840332f, 0.918457f, -1.6875f, -24.0000f, 15.0000f, 19, 22}, // ffb9 + {0.856934f, 0.915527f, 0.865723f, 0.926270f, -1.4375f, -23.9375f, 15.0000f, 18, 22}, // ffba + {0.755859f, 0.139160f, 0.763184f, 0.149902f, 0.1250f, -23.9375f, 15.0000f, 15, 22}, // ffbb + {0.867188f, 0.622559f, 0.875000f, 0.633301f, -0.3125f, -23.9375f, 15.0000f, 16, 22}, // ffbc + {0.725586f, 0.675781f, 0.733398f, 0.686523f, -0.1875f, -23.9375f, 15.0000f, 16, 22}, // ffbd + {0.423340f, 0.916992f, 0.431641f, 0.927734f, -0.6875f, -23.9375f, 15.0000f, 17, 22}, // ffbe + {0.893555f, 0.801270f, 0.906738f, 0.814453f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffbf + {0.907227f, 0.801270f, 0.920410f, 0.814453f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc0 + {0.624023f, 0.801758f, 0.637207f, 0.814941f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc1 + {0.000000f, 0.908203f, 0.006348f, 0.923828f, 1.1250f, -29.2500f, 15.0000f, 13, 32}, // ffc2 + {0.469727f, 0.902832f, 0.476563f, 0.918457f, 0.8125f, -29.2500f, 15.0000f, 14, 32}, // ffc3 + {0.027832f, 0.908203f, 0.034180f, 0.923828f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffc4 + {0.507813f, 0.902832f, 0.514648f, 0.918457f, 0.6875f, -29.2500f, 15.0000f, 14, 32}, // ffc5 + {0.063477f, 0.908203f, 0.069824f, 0.923828f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffc6 + {0.795898f, 0.867676f, 0.804199f, 0.883301f, -0.8125f, -29.3125f, 15.0000f, 17, 32}, // ffc7 + {0.941895f, 0.802246f, 0.955078f, 0.815430f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc8 + {0.065430f, 0.802734f, 0.078613f, 0.815918f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffc9 + {0.205078f, 0.908203f, 0.211426f, 0.923828f, 1.0625f, -29.2500f, 15.0000f, 13, 32}, // ffca + {0.083984f, 0.868164f, 0.092285f, 0.883789f, -0.8125f, -29.3125f, 15.0000f, 17, 32}, // ffcb + {0.794922f, 0.086426f, 0.803223f, 0.094727f, -0.6875f, -22.4375f, 15.0000f, 17, 17}, // ffcc + {0.796875f, 0.851563f, 0.805664f, 0.867188f, -1.3125f, -29.2500f, 15.0000f, 18, 32}, // ffcd + {0.349121f, 0.852051f, 0.357910f, 0.867676f, -1.1875f, -29.2500f, 15.0000f, 18, 32}, // ffce + {0.333984f, 0.868164f, 0.342285f, 0.883789f, -1.3125f, -29.2500f, 15.0000f, 17, 32}, // ffcf + {0.106445f, 0.803223f, 0.119629f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd0 + {0.120117f, 0.803223f, 0.133301f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd1 + {0.391602f, 0.047363f, 0.400391f, 0.055664f, -1.1250f, -22.4375f, 15.0000f, 18, 17}, // ffd2 + {0.548828f, 0.203125f, 0.557129f, 0.212402f, -0.8125f, -20.6875f, 15.0000f, 17, 19}, // ffd3 + {0.342773f, 0.868164f, 0.351074f, 0.883789f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffd4 + {0.358398f, 0.852051f, 0.367188f, 0.867676f, -1.2500f, -29.3125f, 15.0000f, 18, 32}, // ffd5 + {0.351563f, 0.868164f, 0.359863f, 0.883789f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffd6 + {0.497559f, 0.304199f, 0.505859f, 0.313477f, -0.8125f, -21.6250f, 15.0000f, 17, 19}, // ffd7 + {0.133789f, 0.803223f, 0.146973f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd8 + {0.256348f, 0.803223f, 0.269531f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffd9 + {0.681641f, 0.135254f, 0.690430f, 0.138672f, -1.1875f, -17.0625f, 15.0000f, 18, 7}, // ffda + {0.555664f, 0.868164f, 0.563965f, 0.883789f, -1.1250f, -29.2500f, 15.0000f, 17, 32}, // ffdb + {0.543945f, 0.722656f, 0.547363f, 0.738281f, 4.3750f, -29.2500f, 15.0000f, 7, 32}, // ffdc + {0.547363f, 0.803223f, 0.560547f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffdd + {0.689941f, 0.803223f, 0.703125f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffde + {0.789551f, 0.803223f, 0.802734f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffdf + {0.555176f, 0.852051f, 0.563965f, 0.867676f, 6.1875f, -25.5000f, 30.0000f, 18, 32}, // ffe0 + {0.376953f, 0.874512f, 0.386719f, 0.887695f, 5.2500f, -25.8750f, 30.0000f, 20, 27}, // ffe1 + {0.601074f, 0.116211f, 0.610352f, 0.123047f, 5.8750f, -19.1250f, 30.0000f, 19, 14}, // ffe2 + {0.409180f, 0.132324f, 0.418945f, 0.135254f, 5.3125f, -29.3125f, 30.0000f, 20, 6}, // ffe3 + {0.861816f, 0.807129f, 0.865234f, 0.822754f, 11.8750f, -25.5000f, 30.0000f, 7, 32}, // ffe4 + {0.487305f, 0.867188f, 0.497559f, 0.879883f, 4.6875f, -25.5000f, 30.0000f, 21, 26}, // ffe5 + {0.503906f, 0.706055f, 0.519531f, 0.718750f, -0.8750f, -25.5000f, 30.0000f, 32, 26}, // ffe6 + {0.955566f, 0.803223f, 0.968750f, 0.816406f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffe7 + {0.996094f, 0.385254f, 0.999512f, 0.405273f, 4.1875f, -33.8125f, 15.0000f, 7, 41}, // ffe8 + {0.564941f, 0.212402f, 0.573242f, 0.219238f, -0.8125f, -16.3750f, 15.0000f, 17, 14}, // ffe9 + {0.602051f, 0.074219f, 0.608887f, 0.082520f, 0.7500f, -16.6250f, 15.0000f, 14, 17}, // ffea + {0.111816f, 0.245605f, 0.120117f, 0.252441f, -0.8125f, -16.3750f, 15.0000f, 17, 14}, // ffeb + {0.682617f, 0.092285f, 0.689453f, 0.100586f, 0.7500f, -16.6250f, 15.0000f, 14, 17}, // ffec + {0.376953f, 0.111816f, 0.385254f, 0.120117f, -1.0000f, -21.7500f, 15.0000f, 17, 17}, // ffed + {0.354492f, 0.144043f, 0.362793f, 0.152344f, -0.9375f, -21.6875f, 15.0000f, 17, 17}, // ffee + {0.488770f, 0.803711f, 0.501953f, 0.816895f, 1.7500f, -26.5000f, 30.0000f, 27, 27}, // ffef }; const AtlasCharRange font_UBUNTU24_ranges[] = { { 32, 128, 0 }, @@ -33537,16 +33838,18 @@ const AtlasCharRange font_UBUNTU24_ranges[] = { { 1024, 1280, 319 }, { 8481, 8483, 575 }, { 65533, 65534, 577 }, - { 880, 1024, 578 }, - { 1424, 1536, 722 }, - { 12288, 12352, 834 }, - { 12353, 12440, 898 }, - { 12441, 12448, 985 }, - { 12448, 12544, 992 }, - { 12784, 12800, 1088 }, - { 19968, 40960, 1104 }, - { 44032, 55204, 22096 }, - { 65280, 65520, 33268 }, + { 384, 593, 578 }, + { 880, 1024, 787 }, + { 1424, 1536, 931 }, + { 7840, 7930, 1043 }, + { 12288, 12352, 1133 }, + { 12353, 12440, 1197 }, + { 12441, 12448, 1284 }, + { 12448, 12544, 1291 }, + { 12784, 12800, 1387 }, + { 19968, 40960, 1403 }, + { 44032, 55204, 22395 }, + { 65280, 65520, 33567 }, }; const AtlasFont font_UBUNTU24 = { -8.968750f, // padding @@ -33555,40 +33858,49 @@ const AtlasFont font_UBUNTU24 = { 0.750000f, // distslope font_UBUNTU24_chardata, font_UBUNTU24_ranges, - 17, + 19, "UBUNTU24", // name }; const AtlasFont *ui_fonts[1] = { &font_UBUNTU24, }; -const AtlasImage ui_images[24] = { - {0.288330f, 0.304932f, 0.295654f, 0.312256f, 16, 16, "I_SOLIDWHITE"}, - {0.127686f, 0.351318f, 0.142334f, 0.365967f, 31, 31, "I_CROSS"}, - {0.762451f, 0.032471f, 0.777588f, 0.047607f, 32, 32, "I_CIRCLE"}, - {0.394287f, 0.462646f, 0.407959f, 0.476318f, 29, 29, "I_SQUARE"}, - {0.688232f, 0.351318f, 0.704346f, 0.364990f, 34, 29, "I_TRIANGLE"}, - {0.000244f, 0.628174f, 0.033447f, 0.634033f, 69, 13, "I_SELECT"}, - {0.399170f, 0.707764f, 0.427002f, 0.713623f, 58, 13, "I_START"}, - {0.893311f, 0.555908f, 0.899170f, 0.567627f, 13, 25, "I_ARROW"}, - {0.393311f, 0.000244f, 0.421631f, 0.020264f, 59, 42, "I_DIR"}, - {0.366455f, 0.000244f, 0.392334f, 0.025635f, 54, 53, "I_ROUND"}, - {0.142334f, 0.000244f, 0.184326f, 0.041260f, 87, 85, "I_STICK"}, - {0.309814f, 0.000244f, 0.365479f, 0.016846f, 115, 35, "I_SHOULDER"}, - {0.621338f, 0.660400f, 0.635010f, 0.674072f, 29, 29, "I_CHECKEDBOX"}, - {0.422607f, 0.000244f, 0.460693f, 0.014404f, 79, 30, "I_RECT"}, - {0.000244f, 0.000244f, 0.059814f, 0.058838f, 123, 121, "I_STICKBG"}, - {0.185303f, 0.000244f, 0.237549f, 0.030518f, 108, 63, "I_BG"}, - {0.347900f, 0.237061f, 0.351807f, 0.243896f, 9, 15, "I_L"}, - {0.327393f, 0.317139f, 0.333252f, 0.323975f, 13, 15, "I_R"}, - {0.461670f, 0.000244f, 0.484619f, 0.023193f, 48, 48, "I_DROP_SHADOW"}, - {0.832275f, 0.351318f, 0.849854f, 0.363525f, 37, 26, "I_LINES"}, - {0.321045f, 0.576904f, 0.338623f, 0.588623f, 37, 25, "I_GRID"}, - {0.060791f, 0.000244f, 0.141357f, 0.028076f, 166, 58, "I_LOGO"}, - {0.238525f, 0.000244f, 0.273193f, 0.034912f, 72, 72, "I_ICON"}, - {0.274170f, 0.000244f, 0.308838f, 0.034912f, 72, 72, "I_ICONGOLD"}, +const AtlasImage ui_images[33] = { + {0.794678f, 0.241943f, 0.802002f, 0.249268f, 16, 16, "I_SOLIDWHITE"}, + {0.958740f, 0.000244f, 0.976318f, 0.017822f, 37, 37, "I_CROSS"}, + {0.918701f, 0.000244f, 0.937256f, 0.018799f, 39, 39, "I_CIRCLE"}, + {0.860107f, 0.015381f, 0.876709f, 0.031982f, 35, 35, "I_SQUARE"}, + {0.938232f, 0.000244f, 0.957764f, 0.016846f, 41, 35, "I_TRIANGLE"}, + {0.582275f, 0.017822f, 0.622314f, 0.025146f, 83, 16, "I_SELECT"}, + {0.675537f, 0.019775f, 0.708740f, 0.027100f, 69, 16, "I_START"}, + {0.676025f, 0.902100f, 0.682861f, 0.916260f, 15, 30, "I_ARROW"}, + {0.810303f, 0.000244f, 0.838623f, 0.020264f, 59, 42, "I_DIR"}, + {0.783447f, 0.000244f, 0.809326f, 0.025635f, 54, 53, "I_ROUND"}, + {0.839600f, 0.000244f, 0.877686f, 0.014404f, 79, 30, "I_RECT"}, + {0.258545f, 0.000244f, 0.300537f, 0.041260f, 87, 85, "I_STICK"}, + {0.063721f, 0.000244f, 0.123291f, 0.058838f, 123, 121, "I_STICK_BG"}, + {0.582275f, 0.000244f, 0.637939f, 0.016846f, 115, 35, "I_SHOULDER"}, + {0.638916f, 0.000244f, 0.674561f, 0.026123f, 74, 54, "I_DIR_LINE"}, + {0.549072f, 0.000244f, 0.581299f, 0.031982f, 67, 66, "I_ROUND_LINE"}, + {0.675537f, 0.000244f, 0.722900f, 0.018799f, 98, 39, "I_RECT_LINE"}, + {0.407959f, 0.000244f, 0.476807f, 0.021729f, 142, 45, "I_SHOULDER_LINE"}, + {0.124268f, 0.000244f, 0.176025f, 0.051025f, 107, 105, "I_STICK_LINE"}, + {0.000244f, 0.000244f, 0.062744f, 0.061768f, 129, 127, "I_STICK_BG_LINE"}, + {0.938232f, 0.017822f, 0.954834f, 0.034424f, 35, 35, "I_CHECKEDBOX"}, + {0.301514f, 0.000244f, 0.353760f, 0.030518f, 108, 63, "I_BG"}, + {0.354736f, 0.000244f, 0.406982f, 0.030518f, 108, 63, "I_BG_GOLD"}, + {0.576904f, 0.049072f, 0.581787f, 0.057373f, 11, 18, "I_L"}, + {0.762451f, 0.167236f, 0.769775f, 0.175537f, 16, 18, "I_R"}, + {0.878662f, 0.000244f, 0.901611f, 0.023193f, 48, 48, "I_DROP_SHADOW"}, + {0.971924f, 0.371826f, 0.989502f, 0.384033f, 37, 26, "I_LINES"}, + {0.951904f, 0.602783f, 0.969482f, 0.614502f, 37, 25, "I_GRID"}, + {0.177002f, 0.000244f, 0.257568f, 0.028076f, 166, 58, "I_LOGO"}, + {0.477783f, 0.000244f, 0.512451f, 0.034912f, 72, 72, "I_ICON"}, + {0.513428f, 0.000244f, 0.548096f, 0.034912f, 72, 72, "I_ICONGOLD"}, + {0.723877f, 0.000244f, 0.752197f, 0.025635f, 59, 53, "I_FOLDER"}, + {0.753174f, 0.000244f, 0.782471f, 0.023193f, 61, 48, "I_UP_DIRECTORY"}, }; const Atlas ui_atlas = { "ui_atlas.zim", ui_fonts, 1, - ui_images, 24, + ui_images, 33, }; diff --git a/UI/ui_atlas.h b/UI/ui_atlas.h index 2ff7cdb10a..dd8afdfdbf 100644 --- a/UI/ui_atlas.h +++ b/UI/ui_atlas.h @@ -18,21 +18,30 @@ #define I_ARROW 7 #define I_DIR 8 #define I_ROUND 9 -#define I_STICK 10 -#define I_SHOULDER 11 -#define I_CHECKEDBOX 12 -#define I_RECT 13 -#define I_STICKBG 14 -#define I_BG 15 -#define I_L 16 -#define I_R 17 -#define I_DROP_SHADOW 18 -#define I_LINES 19 -#define I_GRID 20 -#define I_LOGO 21 -#define I_ICON 22 -#define I_ICONGOLD 23 +#define I_RECT 10 +#define I_STICK 11 +#define I_STICK_BG 12 +#define I_SHOULDER 13 +#define I_DIR_LINE 14 +#define I_ROUND_LINE 15 +#define I_RECT_LINE 16 +#define I_SHOULDER_LINE 17 +#define I_STICK_LINE 18 +#define I_STICK_BG_LINE 19 +#define I_CHECKEDBOX 20 +#define I_BG 21 +#define I_BG_GOLD 22 +#define I_L 23 +#define I_R 24 +#define I_DROP_SHADOW 25 +#define I_LINES 26 +#define I_GRID 27 +#define I_LOGO 28 +#define I_ICON 29 +#define I_ICONGOLD 30 +#define I_FOLDER 31 +#define I_UP_DIRECTORY 32 extern const Atlas ui_atlas; -extern const AtlasImage ui_images[24]; +extern const AtlasImage ui_images[33]; diff --git a/UI/ui_atlas_lowmem.cpp b/UI/ui_atlas_lowmem.cpp index c9bf28c744..6e0ee98978 100644 --- a/UI/ui_atlas_lowmem.cpp +++ b/UI/ui_atlas_lowmem.cpp @@ -3,642 +3,160 @@ #include "ui_atlas.h" const AtlasChar font_UBUNTU24_chardata[] = { -// RANGE: 0x20 - 0x80, start 0x18 - {0.000000f, 0.000000f, 0.000488f, 0.003906f, -2.0000f, -4.0000f, 7.5000f, 1, 1}, // 0020 - {0.423828f, 0.613281f, 0.427734f, 0.726563f, 0.2500f, -28.1875f, 7.8750f, 8, 29}, // 0021 - {0.714355f, 0.234375f, 0.720215f, 0.285156f, 0.1875f, -28.1875f, 11.6875f, 12, 13}, // 0022 - {0.079102f, 0.519531f, 0.088867f, 0.632813f, -1.0625f, -28.1875f, 18.0000f, 20, 29}, // 0023 - {0.812500f, 0.398438f, 0.821289f, 0.539063f, -0.2500f, -32.0000f, 17.3125f, 18, 36}, // 0024 - {0.187500f, 0.367188f, 0.199219f, 0.480469f, -0.3750f, -28.5000f, 22.6875f, 24, 29}, // 0025 - {0.908691f, 0.406250f, 0.919434f, 0.519531f, -0.8750f, -28.5000f, 19.7500f, 22, 29}, // 0026 - {0.131836f, 0.375000f, 0.135742f, 0.425781f, -0.1875f, -28.1875f, 6.8125f, 8, 13}, // 0027 - {0.845703f, 0.656250f, 0.851563f, 0.808594f, -0.0625f, -31.0000f, 10.0625f, 12, 39}, // 0028 - {0.517090f, 0.707031f, 0.522949f, 0.859375f, -1.6250f, -31.0000f, 10.1250f, 12, 39}, // 0029 - {0.906250f, 0.808594f, 0.913574f, 0.871094f, -0.8750f, -21.9375f, 13.1875f, 15, 16}, // 002a - {0.083984f, 0.753906f, 0.093262f, 0.839844f, -0.8750f, -24.0625f, 17.2500f, 19, 22}, // 002b - {0.562988f, 0.394531f, 0.567383f, 0.445313f, -1.0625f, -7.5625f, 6.8750f, 9, 13}, // 002c - {0.708008f, 0.378906f, 0.714355f, 0.406250f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 002d - {0.131836f, 0.429688f, 0.135742f, 0.460938f, 0.3125f, -7.3750f, 8.3125f, 8, 8}, // 002e - {0.991699f, 0.343750f, 0.999512f, 0.464844f, -1.8750f, -28.2500f, 12.1250f, 16, 31}, // 002f - {0.130859f, 0.597656f, 0.140137f, 0.710938f, -0.3125f, -28.5000f, 17.5625f, 19, 29}, // 0030 - {0.438477f, 0.789063f, 0.444824f, 0.902344f, 1.0625f, -28.5625f, 17.5625f, 13, 29}, // 0031 - {0.140625f, 0.597656f, 0.149902f, 0.710938f, -0.2500f, -28.5000f, 17.5000f, 19, 29}, // 0032 - {0.150391f, 0.597656f, 0.159668f, 0.710938f, -0.3750f, -28.5000f, 17.5000f, 19, 29}, // 0033 - {0.893066f, 0.519531f, 0.902832f, 0.632813f, -0.8750f, -28.1875f, 17.5625f, 20, 29}, // 0034 - {0.063477f, 0.644531f, 0.072266f, 0.757813f, 0.1250f, -28.1875f, 17.5000f, 18, 29}, // 0035 - {0.160156f, 0.597656f, 0.169434f, 0.710938f, -0.0625f, -28.5000f, 17.5625f, 19, 29}, // 0036 - {0.396484f, 0.597656f, 0.405762f, 0.710938f, -0.6250f, -28.1875f, 17.5625f, 19, 29}, // 0037 - {0.583984f, 0.597656f, 0.593262f, 0.710938f, -0.5000f, -28.5000f, 17.5625f, 19, 29}, // 0038 - {0.977051f, 0.597656f, 0.986328f, 0.710938f, -0.5625f, -28.5000f, 17.5000f, 19, 29}, // 0039 - {0.671875f, 0.148438f, 0.675781f, 0.234375f, 0.3125f, -21.9375f, 7.9375f, 8, 22}, // 003a - {0.074707f, 0.527344f, 0.079102f, 0.632813f, -0.1875f, -21.9375f, 7.8750f, 9, 27}, // 003b - {0.207520f, 0.808594f, 0.215332f, 0.886719f, -1.0000f, -20.6875f, 15.1250f, 16, 20}, // 003c - {0.341797f, 0.816406f, 0.350098f, 0.871094f, 0.1875f, -20.1250f, 16.9375f, 17, 14}, // 003d - {0.192871f, 0.808594f, 0.201172f, 0.886719f, -0.1250f, -20.5000f, 15.3750f, 17, 20}, // 003e - {0.018555f, 0.714844f, 0.026855f, 0.828125f, -1.2500f, -28.5625f, 14.3750f, 17, 29}, // 003f - {0.632813f, 0.000000f, 0.646973f, 0.140625f, -0.5000f, -27.6250f, 27.5625f, 29, 36}, // 0040 - {0.493164f, 0.410156f, 0.503906f, 0.523438f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0041 - {0.679688f, 0.523438f, 0.689453f, 0.636719f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0042 - {0.903320f, 0.523438f, 0.913086f, 0.636719f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0043 - {0.054199f, 0.527344f, 0.063965f, 0.640625f, 0.3125f, -28.1875f, 19.8125f, 20, 29}, // 0044 - {0.488770f, 0.644531f, 0.497559f, 0.757813f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0045 - {0.448730f, 0.648438f, 0.457520f, 0.761719f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0046 - {0.882324f, 0.476563f, 0.892578f, 0.589844f, -0.3125f, -28.5000f, 19.8750f, 21, 29}, // 0047 - {0.131836f, 0.480469f, 0.142090f, 0.593750f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 0048 - {0.673828f, 0.812500f, 0.677734f, 0.925781f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0049 - {0.619629f, 0.652344f, 0.628418f, 0.765625f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 004a - {0.142578f, 0.480469f, 0.152832f, 0.593750f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 004b - {0.628906f, 0.652344f, 0.637695f, 0.765625f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 004c - {0.649414f, 0.289063f, 0.661621f, 0.402344f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 004d - {0.153320f, 0.480469f, 0.163574f, 0.593750f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 004e - {0.187500f, 0.484375f, 0.197754f, 0.597656f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 004f - {0.064453f, 0.527344f, 0.074219f, 0.640625f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0050 - {0.823730f, 0.277344f, 0.834961f, 0.402344f, -0.3750f, -28.5625f, 20.6250f, 23, 32}, // 0051 - {0.493652f, 0.527344f, 0.503418f, 0.640625f, 0.3125f, -28.1875f, 18.9375f, 20, 29}, // 0052 - {0.449219f, 0.531250f, 0.458984f, 0.644531f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0053 - {0.198242f, 0.484375f, 0.208496f, 0.597656f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0054 - {0.208984f, 0.484375f, 0.219238f, 0.597656f, 0.0625f, -28.1875f, 20.1250f, 21, 29}, // 0055 - {0.120117f, 0.375000f, 0.131348f, 0.488281f, -1.6875f, -28.1875f, 18.6875f, 23, 29}, // 0056 - {0.753906f, 0.117188f, 0.768066f, 0.230469f, -1.5000f, -28.1875f, 25.8125f, 29, 29}, // 0057 - {0.449219f, 0.414063f, 0.459961f, 0.527344f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0058 - {0.831055f, 0.417969f, 0.841797f, 0.531250f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 0059 - {0.986816f, 0.597656f, 0.996094f, 0.710938f, -0.6875f, -28.1875f, 16.6875f, 19, 29}, // 005a - {0.805664f, 0.785156f, 0.810547f, 0.933594f, 0.1250f, -31.8125f, 8.4375f, 10, 38}, // 005b - {0.046875f, 0.703125f, 0.054688f, 0.824219f, -1.6250f, -28.2500f, 12.3750f, 16, 31}, // 005c - {0.811035f, 0.785156f, 0.815918f, 0.933594f, -1.8125f, -31.8125f, 8.3750f, 10, 38}, // 005d - {0.657715f, 0.808594f, 0.665039f, 0.875000f, -1.1250f, -28.2500f, 12.7500f, 15, 17}, // 005e - {0.507813f, 0.820313f, 0.516113f, 0.847656f, -1.8750f, -4.0625f, 13.3125f, 17, 7}, // 005f - {0.407715f, 0.312500f, 0.413086f, 0.347656f, -0.8750f, -29.2500f, 9.8750f, 11, 9}, // 0060 - {0.170410f, 0.753906f, 0.179199f, 0.843750f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0061 - {0.349121f, 0.570313f, 0.357910f, 0.691406f, -0.0625f, -29.8750f, 16.7500f, 18, 31}, // 0062 - {0.248535f, 0.777344f, 0.256836f, 0.867188f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0063 - {0.557617f, 0.570313f, 0.566406f, 0.691406f, -0.6875f, -29.8750f, 16.7500f, 18, 31}, // 0064 - {0.523438f, 0.753906f, 0.532227f, 0.843750f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0065 - {0.368652f, 0.742188f, 0.375488f, 0.863281f, -1.3125f, -30.2500f, 10.0625f, 14, 31}, // 0066 - {0.639648f, 0.613281f, 0.648438f, 0.730469f, -0.6250f, -22.3125f, 16.7500f, 18, 30}, // 0067 - {0.541992f, 0.664063f, 0.550293f, 0.781250f, -0.1250f, -29.9375f, 16.6875f, 17, 30}, // 0068 - {0.215820f, 0.808594f, 0.219727f, 0.925781f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0069 - {0.482910f, 0.726563f, 0.488281f, 0.875000f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 006a - {0.689941f, 0.613281f, 0.698730f, 0.730469f, -0.0625f, -29.9375f, 15.5000f, 18, 30}, // 006b - {0.914063f, 0.808594f, 0.917969f, 0.925781f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 006c - {0.919922f, 0.500000f, 0.932617f, 0.589844f, -0.0625f, -22.3125f, 25.6875f, 26, 23}, // 006d - {0.257324f, 0.777344f, 0.265625f, 0.867188f, -0.0625f, -22.3125f, 16.8125f, 17, 23}, // 006e - {0.688965f, 0.734375f, 0.698242f, 0.824219f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 006f - {0.723633f, 0.613281f, 0.732422f, 0.730469f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0070 - {0.732910f, 0.613281f, 0.741699f, 0.730469f, -0.6875f, -22.2500f, 16.7500f, 18, 30}, // 0071 - {0.732422f, 0.140625f, 0.738770f, 0.230469f, -0.0625f, -22.3125f, 10.4375f, 13, 23}, // 0072 - {0.266113f, 0.777344f, 0.274414f, 0.867188f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0073 - {0.135742f, 0.230469f, 0.142090f, 0.335938f, -1.5000f, -26.4375f, 10.1875f, 13, 27}, // 0074 - {0.274902f, 0.777344f, 0.283203f, 0.867188f, -0.1250f, -21.9375f, 16.7500f, 17, 23}, // 0075 - {0.318359f, 0.753906f, 0.327637f, 0.839844f, -1.5000f, -22.0000f, 15.0000f, 19, 22}, // 0076 - {0.029297f, 0.613281f, 0.041504f, 0.699219f, -1.3750f, -22.0000f, 22.0625f, 25, 22}, // 0077 - {0.852051f, 0.769531f, 0.860840f, 0.855469f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0078 - {0.089355f, 0.519531f, 0.098633f, 0.636719f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0079 - {0.600586f, 0.789063f, 0.608887f, 0.875000f, -0.6875f, -22.0000f, 15.0000f, 17, 22}, // 007a - {0.163574f, 0.714844f, 0.169922f, 0.859375f, -1.1250f, -30.5625f, 10.0000f, 13, 37}, // 007b - {0.848633f, 0.812500f, 0.852051f, 0.941406f, 0.1875f, -28.1875f, 7.4375f, 7, 33}, // 007c - {0.776367f, 0.718750f, 0.782715f, 0.863281f, -1.5000f, -30.5625f, 10.0000f, 13, 37}, // 007d - {0.895508f, 0.820313f, 0.905273f, 0.863281f, -0.1875f, -17.3750f, 19.6250f, 20, 11}, // 007e - {0.553711f, 0.285156f, 0.566895f, 0.390625f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 007f -// RANGE: 0x80 - 0x81, start 0x78 - {0.622070f, 0.285156f, 0.635254f, 0.390625f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0080 -// RANGE: 0xa2 - 0x100, start 0x79 - {0.742188f, 0.613281f, 0.750977f, 0.730469f, -0.7500f, -25.9375f, 16.6875f, 18, 30}, // 00a2 - {0.000000f, 0.601563f, 0.009277f, 0.714844f, -0.7500f, -28.5000f, 17.3750f, 19, 29}, // 00a3 - {0.955078f, 0.500000f, 0.966309f, 0.601563f, -0.5625f, -25.0625f, 21.6875f, 23, 26}, // 00a4 - {0.219727f, 0.484375f, 0.229980f, 0.597656f, -1.5000f, -28.1875f, 18.0000f, 21, 29}, // 00a5 - {0.614746f, 0.804688f, 0.618652f, 0.933594f, 0.0625f, -28.1875f, 7.3750f, 8, 33}, // 00a6 - {0.451660f, 0.265625f, 0.461426f, 0.410156f, -0.5000f, -28.5000f, 18.3750f, 20, 37}, // 00a7 - {0.177246f, 0.335938f, 0.184570f, 0.367188f, 0.5000f, -28.1875f, 15.8125f, 15, 8}, // 00a8 - {0.930176f, 0.234375f, 0.942871f, 0.347656f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00a9 - {0.936523f, 0.351563f, 0.943359f, 0.421875f, -0.1875f, -28.5625f, 13.3125f, 14, 18}, // 00aa - {0.414551f, 0.167969f, 0.422363f, 0.238281f, -0.5625f, -19.1875f, 14.3750f, 16, 18}, // 00ab - {0.991699f, 0.000000f, 0.999512f, 0.042969f, -0.1250f, -17.1875f, 16.3125f, 16, 11}, // 00ac - {0.913574f, 0.523438f, 0.919922f, 0.550781f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 00ad - {0.414551f, 0.238281f, 0.427246f, 0.351563f, -0.5625f, -28.5000f, 24.2500f, 26, 29}, // 00ae - {0.780273f, 0.136719f, 0.787598f, 0.164063f, 0.0625f, -28.1875f, 14.7500f, 15, 7}, // 00af - {0.054199f, 0.476563f, 0.060059f, 0.527344f, 0.0625f, -28.5625f, 11.8750f, 12, 13}, // 00b0 - {0.118164f, 0.726563f, 0.126953f, 0.828125f, -0.5000f, -25.2500f, 16.6250f, 18, 26}, // 00b1 - {0.951172f, 0.117188f, 0.957520f, 0.187500f, -0.3125f, -28.5625f, 12.4375f, 13, 18}, // 00b2 - {0.919922f, 0.406250f, 0.926758f, 0.476563f, -0.4375f, -28.5625f, 12.5625f, 14, 18}, // 00b3 - {0.230469f, 0.484375f, 0.235840f, 0.519531f, -0.1250f, -29.2500f, 10.3125f, 11, 9}, // 00b4 - {0.128418f, 0.714844f, 0.136719f, 0.828125f, 0.1875f, -21.9375f, 17.5000f, 17, 29}, // 00b5 - {0.466797f, 0.726563f, 0.474609f, 0.839844f, -1.0000f, -28.1875f, 15.0625f, 16, 29}, // 00b6 - {0.955078f, 0.433594f, 0.958984f, 0.464844f, 0.4375f, -17.6250f, 8.4375f, 8, 8}, // 00b7 - {0.786133f, 0.425781f, 0.790527f, 0.472656f, -0.3125f, -4.0000f, 7.7500f, 9, 12}, // 00b8 - {0.387207f, 0.210938f, 0.391602f, 0.281250f, -0.6875f, -28.5625f, 8.2500f, 9, 18}, // 00b9 - {0.566895f, 0.570313f, 0.573730f, 0.640625f, -0.1875f, -28.5625f, 13.5625f, 14, 18}, // 00ba - {0.665527f, 0.812500f, 0.673340f, 0.871094f, -0.0625f, -18.1875f, 14.3750f, 16, 15}, // 00bb - {0.714355f, 0.289063f, 0.726563f, 0.402344f, 0.7500f, -28.5625f, 22.1875f, 25, 29}, // 00bc - {0.597656f, 0.246094f, 0.610352f, 0.359375f, 0.7500f, -28.5625f, 23.2500f, 26, 29}, // 00bd - {0.875977f, 0.117188f, 0.890137f, 0.230469f, -0.1875f, -28.5625f, 25.0625f, 29, 29}, // 00be - {0.137207f, 0.714844f, 0.145508f, 0.828125f, -0.5625f, -21.9375f, 14.6875f, 17, 29}, // 00bf - {0.851074f, 0.136719f, 0.861816f, 0.277344f, -1.5000f, -35.0625f, 18.6875f, 22, 36}, // 00c0 - {0.545410f, 0.144531f, 0.556152f, 0.281250f, -1.5000f, -35.0000f, 18.6875f, 22, 35}, // 00c1 - {0.556641f, 0.144531f, 0.567383f, 0.281250f, -1.5000f, -34.8125f, 18.7500f, 22, 35}, // 00c2 - {0.309570f, 0.140625f, 0.320313f, 0.281250f, -1.5000f, -35.1250f, 18.6875f, 22, 36}, // 00c3 - {0.578125f, 0.253906f, 0.588867f, 0.386719f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 00c4 - {0.320801f, 0.140625f, 0.331543f, 0.281250f, -1.5000f, -35.5625f, 18.6875f, 22, 36}, // 00c5 - {0.910645f, 0.000000f, 0.925781f, 0.113281f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 00c6 - {0.355957f, 0.285156f, 0.365723f, 0.425781f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 00c7 - {0.439941f, 0.402344f, 0.448730f, 0.542969f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 00c8 - {0.767578f, 0.425781f, 0.776367f, 0.562500f, 0.3125f, -35.0000f, 16.4375f, 18, 35}, // 00c9 - {0.776855f, 0.425781f, 0.785645f, 0.562500f, 0.3125f, -34.8125f, 16.4375f, 18, 35}, // 00ca - {0.474121f, 0.472656f, 0.482910f, 0.605469f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 00cb - {0.751465f, 0.761719f, 0.756836f, 0.902344f, -2.8750f, -35.0625f, 8.6250f, 11, 36}, // 00cc - {0.541992f, 0.785156f, 0.547363f, 0.921875f, 0.6250f, -35.0000f, 8.6250f, 11, 35}, // 00cd - {0.559570f, 0.695313f, 0.566406f, 0.832031f, -2.4375f, -34.8125f, 8.6250f, 14, 35}, // 00ce - {0.179199f, 0.632813f, 0.186523f, 0.765625f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 00cf - {0.842285f, 0.421875f, 0.853027f, 0.535156f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 00d0 - {0.780273f, 0.164063f, 0.790527f, 0.304688f, 0.3125f, -35.1250f, 20.8125f, 21, 36}, // 00d1 - {0.393066f, 0.167969f, 0.403320f, 0.308594f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 00d2 - {0.403809f, 0.167969f, 0.414063f, 0.308594f, -0.3750f, -35.3125f, 20.1875f, 21, 36}, // 00d3 - {0.970215f, 0.171875f, 0.980469f, 0.312500f, -0.3750f, -35.1250f, 20.1875f, 21, 36}, // 00d4 - {0.461914f, 0.191406f, 0.472168f, 0.332031f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 00d5 - {0.835449f, 0.277344f, 0.845703f, 0.414063f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 00d6 - {0.959961f, 0.800781f, 0.968750f, 0.878906f, -0.7500f, -22.9375f, 16.4375f, 18, 20}, // 00d7 - {0.682617f, 0.398438f, 0.692871f, 0.519531f, -0.3750f, -29.1250f, 20.2500f, 21, 31}, // 00d8 - {0.472656f, 0.191406f, 0.482910f, 0.332031f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 00d9 - {0.980957f, 0.191406f, 0.991211f, 0.332031f, 0.0625f, -34.9375f, 20.1250f, 21, 36}, // 00da - {0.483398f, 0.195313f, 0.493652f, 0.335938f, 0.0625f, -34.8125f, 20.1250f, 21, 36}, // 00db - {0.846191f, 0.281250f, 0.856445f, 0.417969f, 0.0625f, -33.9375f, 20.1250f, 21, 35}, // 00dc - {0.626953f, 0.144531f, 0.637695f, 0.281250f, -1.5625f, -34.9375f, 18.6875f, 22, 35}, // 00dd - {0.186523f, 0.601563f, 0.195801f, 0.714844f, 0.2500f, -28.1875f, 17.7500f, 19, 29}, // 00de - {0.503906f, 0.542969f, 0.513184f, 0.660156f, 0.0625f, -29.6250f, 18.1250f, 19, 30}, // 00df - {0.652344f, 0.574219f, 0.661133f, 0.695313f, -0.7500f, -29.6875f, 16.0625f, 18, 31}, // 00e0 - {0.863770f, 0.617188f, 0.872559f, 0.734375f, -0.7500f, -29.6250f, 16.0625f, 18, 30}, // 00e1 - {0.099121f, 0.621094f, 0.107910f, 0.738281f, -0.7500f, -29.4375f, 16.0625f, 18, 30}, // 00e2 - {0.933105f, 0.574219f, 0.941895f, 0.695313f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 00e3 - {0.827148f, 0.652344f, 0.835938f, 0.765625f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 00e4 - {0.942383f, 0.574219f, 0.951172f, 0.695313f, -0.7500f, -30.1875f, 16.0625f, 18, 31}, // 00e5 - {0.460449f, 0.472656f, 0.473633f, 0.562500f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 00e6 - {0.807617f, 0.664063f, 0.815918f, 0.781250f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 00e7 - {0.387207f, 0.578125f, 0.395996f, 0.699219f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 00e8 - {0.371094f, 0.621094f, 0.379883f, 0.738281f, -0.7500f, -29.6250f, 15.5000f, 18, 30}, // 00e9 - {0.789063f, 0.625000f, 0.797852f, 0.742188f, -0.7500f, -29.4375f, 15.5000f, 18, 30}, // 00ea - {0.851563f, 0.652344f, 0.860352f, 0.765625f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 00eb - {0.506836f, 0.292969f, 0.512207f, 0.410156f, -3.3125f, -29.3750f, 7.8125f, 11, 30}, // 00ec - {0.201660f, 0.808594f, 0.207031f, 0.925781f, 0.1875f, -29.3125f, 7.8125f, 11, 30}, // 00ed - {0.783203f, 0.746094f, 0.790039f, 0.863281f, -2.8750f, -29.1250f, 7.8125f, 14, 30}, // 00ee - {0.743652f, 0.734375f, 0.750977f, 0.847656f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 00ef - {0.538086f, 0.542969f, 0.547363f, 0.660156f, -1.0000f, -29.1875f, 17.5000f, 19, 30}, // 00f0 - {0.437988f, 0.667969f, 0.446289f, 0.785156f, -0.0625f, -29.7500f, 16.8125f, 17, 30}, // 00f1 - {0.377441f, 0.496094f, 0.386719f, 0.617188f, -0.7500f, -29.6875f, 16.7500f, 19, 31}, // 00f2 - {0.547852f, 0.542969f, 0.557129f, 0.660156f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 00f3 - {0.807617f, 0.542969f, 0.816895f, 0.660156f, -0.7500f, -29.4375f, 16.7500f, 19, 30}, // 00f4 - {0.600098f, 0.503906f, 0.609375f, 0.625000f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 00f5 - {0.196289f, 0.601563f, 0.205566f, 0.714844f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 00f6 - {0.825195f, 0.769531f, 0.834473f, 0.851563f, -0.9375f, -23.7500f, 16.9375f, 19, 21}, // 00f7 - {0.498047f, 0.664063f, 0.507324f, 0.769531f, -0.7500f, -24.1250f, 16.7500f, 19, 27}, // 00f8 - {0.603027f, 0.667969f, 0.611328f, 0.785156f, -0.1250f, -29.3125f, 16.7500f, 17, 30}, // 00f9 - {0.699219f, 0.671875f, 0.707520f, 0.789063f, -0.1250f, -29.2500f, 16.7500f, 17, 30}, // 00fa - {0.708008f, 0.671875f, 0.716309f, 0.789063f, -0.1250f, -29.1250f, 16.7500f, 17, 30}, // 00fb - {0.145996f, 0.714844f, 0.154297f, 0.828125f, -0.1250f, -28.1875f, 16.7500f, 17, 29}, // 00fc - {0.483398f, 0.339844f, 0.492676f, 0.484375f, -1.6875f, -29.3125f, 15.0000f, 19, 37}, // 00fd - {0.758301f, 0.378906f, 0.767090f, 0.523438f, 0.0625f, -29.8750f, 16.8750f, 18, 37}, // 00fe - {0.802734f, 0.367188f, 0.812012f, 0.507813f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 00ff -// RANGE: 0x100 - 0x180, start 0xd7 - {0.531738f, 0.257813f, 0.542480f, 0.390625f, -1.5000f, -33.6250f, 18.7500f, 22, 34}, // 0100 - {0.566895f, 0.656250f, 0.575684f, 0.769531f, -0.7500f, -28.2500f, 16.0625f, 18, 29}, // 0101 - {0.332031f, 0.140625f, 0.342773f, 0.281250f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 0102 - {0.513672f, 0.582031f, 0.522461f, 0.703125f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 0103 - {0.450195f, 0.121094f, 0.461426f, 0.261719f, -1.5000f, -28.1875f, 18.6875f, 23, 36}, // 0104 - {0.438965f, 0.546875f, 0.448242f, 0.664063f, -0.7500f, -22.3125f, 16.0625f, 19, 30}, // 0105 - {0.662109f, 0.289063f, 0.671875f, 0.429688f, -0.3125f, -35.3125f, 18.8125f, 20, 36}, // 0106 - {0.816406f, 0.671875f, 0.824707f, 0.789063f, -0.7500f, -29.6250f, 15.4375f, 17, 30}, // 0107 - {0.567383f, 0.304688f, 0.577148f, 0.445313f, -0.3125f, -35.1250f, 18.8125f, 20, 36}, // 0108 - {0.406250f, 0.679688f, 0.414551f, 0.796875f, -0.7500f, -29.4375f, 15.4375f, 17, 30}, // 0109 - {0.366211f, 0.355469f, 0.375977f, 0.492188f, -0.3125f, -34.5000f, 18.8125f, 20, 35}, // 010a - {0.415039f, 0.679688f, 0.423340f, 0.796875f, -0.7500f, -28.8125f, 15.4375f, 17, 30}, // 010b - {0.387207f, 0.312500f, 0.396973f, 0.453125f, -0.3125f, -35.2500f, 18.8125f, 20, 36}, // 010c - {0.758789f, 0.679688f, 0.767090f, 0.796875f, -0.7500f, -29.5000f, 15.4375f, 17, 30}, // 010d - {0.376465f, 0.355469f, 0.386230f, 0.492188f, 0.3125f, -34.9375f, 19.8125f, 20, 35}, // 010e - {0.098633f, 0.375000f, 0.109375f, 0.496094f, -0.6875f, -29.8750f, 16.7500f, 22, 31}, // 010f - {0.236328f, 0.425781f, 0.247070f, 0.539063f, -1.8750f, -28.1875f, 19.7500f, 22, 29}, // 0110 - {0.166504f, 0.472656f, 0.176270f, 0.593750f, -0.6875f, -29.8750f, 16.7500f, 20, 31}, // 0111 - {0.035645f, 0.476563f, 0.044434f, 0.609375f, 0.3125f, -33.6250f, 16.4375f, 18, 34}, // 0112 - {0.836426f, 0.656250f, 0.845215f, 0.769531f, -0.7500f, -28.3125f, 15.5000f, 18, 29}, // 0113 - {0.609863f, 0.402344f, 0.618652f, 0.542969f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 0114 - {0.020020f, 0.589844f, 0.028809f, 0.710938f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 0115 - {0.348633f, 0.429688f, 0.357422f, 0.566406f, 0.3125f, -34.1875f, 16.4375f, 18, 35}, // 0116 - {0.798340f, 0.625000f, 0.807129f, 0.742188f, -0.7500f, -28.8125f, 15.5000f, 18, 30}, // 0117 - {0.708008f, 0.406250f, 0.716797f, 0.546875f, 0.3125f, -28.1875f, 16.4375f, 18, 36}, // 0118 - {0.225586f, 0.660156f, 0.234375f, 0.773438f, -0.7500f, -22.3125f, 15.5000f, 18, 29}, // 0119 - {0.656738f, 0.433594f, 0.665527f, 0.570313f, 0.3125f, -34.9375f, 16.4375f, 18, 35}, // 011a - {0.593750f, 0.628906f, 0.602539f, 0.746094f, -0.7500f, -29.5625f, 15.5000f, 18, 30}, // 011b - {0.951172f, 0.195313f, 0.961426f, 0.335938f, -0.3125f, -35.1250f, 19.8750f, 21, 36}, // 011c - {0.577637f, 0.390625f, 0.586426f, 0.535156f, -0.6250f, -29.5000f, 16.7500f, 18, 37}, // 011d - {0.365723f, 0.210938f, 0.375977f, 0.351563f, -0.3125f, -35.4375f, 19.8750f, 21, 36}, // 011e - {0.060547f, 0.375000f, 0.069336f, 0.523438f, -0.6250f, -29.8125f, 16.7500f, 18, 38}, // 011f - {0.237793f, 0.285156f, 0.248047f, 0.421875f, -0.3125f, -34.5000f, 19.8750f, 21, 35}, // 0120 - {0.532227f, 0.394531f, 0.541016f, 0.539063f, -0.6250f, -28.8125f, 16.7500f, 18, 37}, // 0121 - {0.721680f, 0.140625f, 0.731934f, 0.285156f, -0.3125f, -28.5000f, 19.8750f, 21, 37}, // 0122 - {0.522949f, 0.285156f, 0.531738f, 0.437500f, -0.6250f, -31.4375f, 16.7500f, 18, 39}, // 0123 - {0.248535f, 0.285156f, 0.258789f, 0.421875f, 0.3125f, -34.8125f, 20.8125f, 21, 35}, // 0124 - {0.512207f, 0.144531f, 0.520508f, 0.281250f, -0.1250f, -34.8125f, 16.6875f, 17, 35}, // 0125 - {0.901367f, 0.289063f, 0.913574f, 0.402344f, -1.5625f, -28.1875f, 20.8125f, 25, 29}, // 0126 - {0.609863f, 0.546875f, 0.619141f, 0.664063f, -2.1250f, -29.9375f, 16.7500f, 19, 30}, // 0127 - {0.925781f, 0.593750f, 0.933105f, 0.734375f, -2.8750f, -35.1250f, 8.5625f, 15, 36}, // 0128 - {0.696289f, 0.261719f, 0.703613f, 0.378906f, -3.2500f, -29.4375f, 7.8125f, 15, 30}, // 0129 - {0.576172f, 0.656250f, 0.583496f, 0.789063f, -3.0000f, -33.6250f, 8.6250f, 15, 34}, // 012a - {0.790527f, 0.746094f, 0.797852f, 0.855469f, -3.4375f, -27.9375f, 7.8125f, 15, 28}, // 012b - {0.716797f, 0.671875f, 0.723633f, 0.812500f, -2.4375f, -35.1250f, 8.6250f, 14, 36}, // 012c - {0.798340f, 0.746094f, 0.805176f, 0.863281f, -2.8125f, -29.4375f, 7.8750f, 14, 30}, // 012d - {0.609375f, 0.804688f, 0.614258f, 0.945313f, -1.2500f, -28.1875f, 8.6250f, 10, 36}, // 012e - {0.576172f, 0.792969f, 0.581055f, 0.937500f, -1.6875f, -29.9375f, 7.7500f, 10, 37}, // 012f - {0.328125f, 0.753906f, 0.332031f, 0.890625f, 0.3750f, -34.1875f, 8.6250f, 8, 35}, // 0130 - {0.578125f, 0.152344f, 0.582031f, 0.238281f, 0.1875f, -22.0000f, 7.8125f, 8, 22}, // 0131 - {0.914063f, 0.289063f, 0.926270f, 0.402344f, 0.6250f, -28.1875f, 24.9375f, 25, 29}, // 0132 - {0.991699f, 0.191406f, 0.999512f, 0.339844f, 0.1875f, -29.9375f, 15.5625f, 16, 38}, // 0133 - {0.259277f, 0.285156f, 0.269531f, 0.421875f, -1.1250f, -34.5625f, 16.3125f, 21, 35}, // 0134 - {0.751465f, 0.613281f, 0.758301f, 0.757813f, -3.0625f, -28.8750f, 8.0000f, 14, 37}, // 0135 - {0.501465f, 0.144531f, 0.511719f, 0.289063f, 0.3125f, -28.1875f, 18.7500f, 21, 37}, // 0136 - {0.069824f, 0.375000f, 0.078613f, 0.523438f, -0.0625f, -29.9375f, 15.5000f, 18, 38}, // 0137 - {0.072754f, 0.757813f, 0.082031f, 0.843750f, 0.1250f, -22.0000f, 17.0000f, 19, 22}, // 0138 - {0.936523f, 0.433594f, 0.945313f, 0.570313f, 0.3125f, -34.1250f, 16.3750f, 18, 35}, // 0139 - {0.055176f, 0.769531f, 0.060547f, 0.910156f, 0.1875f, -35.2500f, 7.7500f, 11, 36}, // 013a - {0.553711f, 0.394531f, 0.562500f, 0.539063f, 0.3125f, -28.2500f, 16.3750f, 18, 37}, // 013b - {0.375977f, 0.742188f, 0.379883f, 0.890625f, -0.3125f, -29.9375f, 7.7500f, 8, 38}, // 013c - {0.234863f, 0.660156f, 0.243652f, 0.773438f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013d - {0.179688f, 0.769531f, 0.186035f, 0.886719f, 0.1875f, -29.9375f, 7.7500f, 13, 30}, // 013e - {0.244141f, 0.660156f, 0.252930f, 0.773438f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 013f - {0.009277f, 0.808594f, 0.015137f, 0.925781f, 0.1875f, -29.9375f, 7.7500f, 12, 30}, // 0140 - {0.206055f, 0.601563f, 0.215332f, 0.714844f, -1.5625f, -28.1875f, 15.3125f, 19, 29}, // 0141 - {0.186523f, 0.808594f, 0.192383f, 0.925781f, -1.5625f, -29.9375f, 8.4375f, 12, 30}, // 0142 - {0.270020f, 0.285156f, 0.280273f, 0.421875f, 0.3125f, -35.0000f, 20.8125f, 21, 35}, // 0143 - {0.767578f, 0.679688f, 0.775879f, 0.796875f, -0.0625f, -29.6250f, 16.8125f, 17, 30}, // 0144 - {0.376465f, 0.210938f, 0.386719f, 0.351563f, 0.3125f, -28.1875f, 20.8125f, 21, 36}, // 0145 - {0.680176f, 0.640625f, 0.688477f, 0.761719f, -0.0625f, -22.3125f, 16.8125f, 17, 31}, // 0146 - {0.280762f, 0.285156f, 0.291016f, 0.421875f, 0.3125f, -34.9375f, 20.8125f, 21, 35}, // 0147 - {0.961426f, 0.679688f, 0.969727f, 0.796875f, -0.0625f, -29.5625f, 16.8125f, 17, 30}, // 0148 - {0.483398f, 0.488281f, 0.493164f, 0.605469f, -2.3125f, -29.8750f, 16.7500f, 20, 30}, // 0149 - {0.890625f, 0.218750f, 0.900879f, 0.359375f, 0.2500f, -28.1875f, 20.6875f, 21, 36}, // 014a - {0.009766f, 0.687500f, 0.018066f, 0.804688f, -0.0625f, -22.3125f, 16.7500f, 17, 30}, // 014b - {0.291504f, 0.285156f, 0.301758f, 0.421875f, -0.3750f, -33.9375f, 20.1875f, 21, 35}, // 014c - {0.215820f, 0.601563f, 0.225098f, 0.714844f, -0.7500f, -28.2500f, 16.7500f, 19, 29}, // 014d - {0.791016f, 0.222656f, 0.801270f, 0.363281f, -0.3750f, -35.4375f, 20.1875f, 21, 36}, // 014e - {0.176758f, 0.507813f, 0.186035f, 0.628906f, -0.7500f, -29.7500f, 16.7500f, 19, 31}, // 014f - {0.801758f, 0.222656f, 0.812012f, 0.363281f, -0.3750f, -35.3750f, 20.1875f, 21, 36}, // 0150 - {0.704102f, 0.550781f, 0.713379f, 0.667969f, -0.7500f, -29.6250f, 16.7500f, 19, 30}, // 0151 - {0.970215f, 0.054688f, 0.984863f, 0.167969f, -0.4375f, -28.5000f, 28.3125f, 30, 29}, // 0152 - {0.943359f, 0.339844f, 0.958496f, 0.429688f, -0.7500f, -22.2500f, 26.6875f, 31, 23}, // 0153 - {0.407715f, 0.355469f, 0.417480f, 0.492188f, 0.3125f, -35.0000f, 18.9375f, 20, 35}, // 0154 - {0.103516f, 0.750000f, 0.110352f, 0.867188f, -0.0625f, -29.6250f, 10.4375f, 14, 30}, // 0155 - {0.397461f, 0.312500f, 0.407227f, 0.453125f, 0.3125f, -28.1875f, 18.9375f, 20, 36}, // 0156 - {0.884277f, 0.234375f, 0.890625f, 0.355469f, -0.3750f, -22.3125f, 10.4375f, 13, 31}, // 0157 - {0.417969f, 0.355469f, 0.427734f, 0.492188f, 0.3125f, -34.9375f, 18.9375f, 20, 35}, // 0158 - {0.110840f, 0.750000f, 0.117676f, 0.867188f, -0.8750f, -29.5625f, 10.5000f, 14, 30}, // 0159 - {0.970703f, 0.316406f, 0.980469f, 0.457031f, -0.5625f, -35.3125f, 18.1250f, 20, 36}, // 015a - {0.458008f, 0.687500f, 0.466309f, 0.804688f, -0.8750f, -29.5625f, 15.0000f, 17, 30}, // 015b - {0.135742f, 0.335938f, 0.145508f, 0.476563f, -0.5625f, -35.1250f, 18.1250f, 20, 36}, // 015c - {0.908203f, 0.687500f, 0.916504f, 0.804688f, -0.8750f, -29.4375f, 15.0000f, 17, 30}, // 015d - {0.767578f, 0.277344f, 0.777344f, 0.421875f, -0.5625f, -28.5625f, 18.1250f, 20, 37}, // 015e - {0.916992f, 0.687500f, 0.925293f, 0.804688f, -0.8750f, -22.3125f, 15.0000f, 17, 30}, // 015f - {0.145996f, 0.335938f, 0.155762f, 0.476563f, -0.5625f, -35.1875f, 18.1250f, 20, 36}, // 0160 - {0.342285f, 0.695313f, 0.350586f, 0.812500f, -0.8750f, -29.5000f, 15.0000f, 17, 30}, // 0161 - {0.060547f, 0.230469f, 0.070801f, 0.371094f, -1.3750f, -28.1875f, 17.3125f, 21, 36}, // 0162 - {0.431641f, 0.726563f, 0.437988f, 0.863281f, -1.5000f, -26.4375f, 10.1875f, 13, 35}, // 0163 - {0.302246f, 0.285156f, 0.312500f, 0.421875f, -1.3750f, -34.8750f, 17.3125f, 21, 35}, // 0164 - {0.423828f, 0.726563f, 0.431152f, 0.847656f, -1.5000f, -30.1875f, 10.1875f, 15, 31}, // 0165 - {0.786133f, 0.484375f, 0.796387f, 0.597656f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0166 - {0.943359f, 0.234375f, 0.950195f, 0.339844f, -1.9375f, -26.4375f, 10.1875f, 14, 27}, // 0167 - {0.071289f, 0.230469f, 0.081543f, 0.371094f, 0.0625f, -35.0625f, 20.1250f, 21, 36}, // 0168 - {0.550781f, 0.695313f, 0.559082f, 0.812500f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 0169 - {0.166504f, 0.335938f, 0.176758f, 0.468750f, 0.0625f, -33.6250f, 20.1250f, 21, 34}, // 016a - {0.154785f, 0.714844f, 0.163086f, 0.828125f, -0.1250f, -27.9375f, 16.7500f, 17, 29}, // 016b - {0.082031f, 0.230469f, 0.092285f, 0.371094f, 0.0625f, -35.1250f, 20.1250f, 21, 36}, // 016c - {0.648926f, 0.699219f, 0.657227f, 0.816406f, -0.1250f, -29.3750f, 16.7500f, 17, 30}, // 016d - {0.092773f, 0.230469f, 0.103027f, 0.371094f, 0.0625f, -35.5625f, 20.1250f, 21, 36}, // 016e - {0.054688f, 0.644531f, 0.062988f, 0.765625f, -0.1250f, -29.8125f, 16.7500f, 17, 31}, // 016f - {0.103516f, 0.230469f, 0.113770f, 0.371094f, 0.0625f, -35.0000f, 20.1250f, 21, 36}, // 0170 - {0.713867f, 0.550781f, 0.723145f, 0.667969f, -0.1250f, -29.3125f, 16.7500f, 19, 30}, // 0171 - {0.114258f, 0.230469f, 0.124512f, 0.371094f, 0.0625f, -28.1875f, 20.1250f, 21, 36}, // 0172 - {0.253418f, 0.660156f, 0.262207f, 0.773438f, -0.1250f, -22.0000f, 16.7500f, 18, 29}, // 0173 - {0.692383f, 0.000000f, 0.706543f, 0.136719f, -1.5000f, -34.8125f, 25.8125f, 29, 35}, // 0174 - {0.427734f, 0.250000f, 0.439941f, 0.367188f, -1.3125f, -29.1250f, 22.0625f, 25, 30}, // 0175 - {0.638184f, 0.144531f, 0.648926f, 0.281250f, -1.5625f, -34.7500f, 18.7500f, 22, 35}, // 0176 - {0.727051f, 0.347656f, 0.736328f, 0.492188f, -1.6875f, -29.1250f, 15.0000f, 19, 37}, // 0177 - {0.685059f, 0.261719f, 0.695801f, 0.394531f, -1.5625f, -33.8750f, 18.7500f, 22, 34}, // 0178 - {0.622070f, 0.394531f, 0.631348f, 0.531250f, -0.6875f, -35.0000f, 16.6875f, 19, 35}, // 0179 - {0.933594f, 0.699219f, 0.941895f, 0.816406f, -0.6875f, -29.3125f, 15.0000f, 17, 30}, // 017a - {0.631836f, 0.394531f, 0.641113f, 0.531250f, -0.6875f, -34.1875f, 16.6875f, 19, 35}, // 017b - {0.389160f, 0.714844f, 0.397461f, 0.828125f, -0.6875f, -28.5000f, 15.0000f, 17, 29}, // 017c - {0.856934f, 0.394531f, 0.866211f, 0.531250f, -0.6875f, -34.9375f, 16.6875f, 19, 35}, // 017d - {0.942383f, 0.699219f, 0.950684f, 0.816406f, -0.6875f, -29.1875f, 15.0000f, 17, 30}, // 017e - {0.993652f, 0.468750f, 0.999512f, 0.589844f, 0.0625f, -30.2500f, 7.6250f, 12, 31}, // 017f -// RANGE: 0x400 - 0x500, start 0x157 - {0.717285f, 0.406250f, 0.726074f, 0.546875f, 0.3125f, -35.0625f, 16.4375f, 18, 36}, // 0400 - {0.044922f, 0.476563f, 0.053711f, 0.609375f, 0.3125f, -33.9375f, 16.4375f, 18, 34}, // 0401 - {0.671875f, 0.246094f, 0.684570f, 0.359375f, -1.0625f, -28.1875f, 22.1875f, 26, 29}, // 0402 - {0.945801f, 0.433594f, 0.954590f, 0.570313f, 0.2500f, -35.0000f, 16.3750f, 18, 35}, // 0403 - {0.619141f, 0.535156f, 0.628906f, 0.648438f, -0.0625f, -28.5625f, 19.1875f, 20, 29}, // 0404 - {0.629395f, 0.535156f, 0.639160f, 0.648438f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0405 - {0.844238f, 0.812500f, 0.848145f, 0.925781f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0406 - {0.611816f, 0.667969f, 0.619141f, 0.800781f, -3.0000f, -33.9375f, 8.6875f, 15, 34}, // 0407 - {0.262695f, 0.660156f, 0.271484f, 0.773438f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 0408 - {0.756348f, 0.000000f, 0.772949f, 0.113281f, -1.2500f, -28.1875f, 31.4375f, 34, 29}, // 0409 - {0.875977f, 0.000000f, 0.891602f, 0.113281f, 0.2500f, -28.1875f, 31.4375f, 32, 29}, // 040a - {0.494141f, 0.292969f, 0.506348f, 0.406250f, -0.8125f, -28.1875f, 23.6875f, 25, 29}, // 040b - {0.461914f, 0.335938f, 0.472168f, 0.468750f, 0.3125f, -33.5000f, 18.8125f, 21, 34}, // 040c - {0.125000f, 0.230469f, 0.135254f, 0.371094f, 0.2500f, -35.0625f, 20.7500f, 21, 36}, // 040d - {0.343262f, 0.140625f, 0.354004f, 0.281250f, -1.3125f, -35.1250f, 18.8750f, 22, 36}, // 040e - {0.312988f, 0.285156f, 0.323242f, 0.421875f, 0.1875f, -28.1875f, 20.7500f, 21, 35}, // 040f - {0.247559f, 0.425781f, 0.258301f, 0.539063f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0410 - {0.831055f, 0.535156f, 0.840820f, 0.648438f, 0.2500f, -28.1875f, 18.6250f, 20, 29}, // 0411 - {0.853516f, 0.535156f, 0.863281f, 0.648438f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0412 - {0.271973f, 0.660156f, 0.280762f, 0.773438f, 0.2500f, -28.1875f, 16.3750f, 18, 29}, // 0413 - {0.957520f, 0.054688f, 0.969727f, 0.191406f, -1.4375f, -28.1875f, 21.7500f, 25, 35}, // 0414 - {0.281250f, 0.660156f, 0.290039f, 0.773438f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0415 - {0.907227f, 0.117188f, 0.921387f, 0.230469f, -1.6875f, -28.1875f, 25.6250f, 29, 29}, // 0416 - {0.120117f, 0.492188f, 0.130371f, 0.605469f, -0.3750f, -28.5000f, 19.6875f, 21, 29}, // 0417 - {0.428223f, 0.492188f, 0.438477f, 0.605469f, 0.2500f, -28.1875f, 20.7500f, 21, 29}, // 0418 - {0.703613f, 0.234375f, 0.713867f, 0.375000f, 0.2500f, -35.1250f, 20.7500f, 21, 36}, // 0419 - {0.366699f, 0.496094f, 0.376953f, 0.609375f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 041a - {0.258789f, 0.425781f, 0.269531f, 0.539063f, -1.2500f, -28.1875f, 20.8125f, 22, 29}, // 041b - {0.777832f, 0.308594f, 0.790039f, 0.421875f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 041c - {0.406738f, 0.496094f, 0.416992f, 0.609375f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 041d - {0.417480f, 0.496094f, 0.427734f, 0.609375f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 041e - {0.641602f, 0.496094f, 0.651855f, 0.609375f, 0.2500f, -28.1875f, 20.8125f, 21, 29}, // 041f - {0.573730f, 0.539063f, 0.583496f, 0.652344f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0420 - {0.841309f, 0.539063f, 0.851074f, 0.652344f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0421 - {0.693359f, 0.496094f, 0.703613f, 0.609375f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0422 - {0.270020f, 0.425781f, 0.280762f, 0.539063f, -1.3125f, -28.1875f, 18.8750f, 22, 29}, // 0423 - {0.199707f, 0.367188f, 0.211426f, 0.480469f, -0.8125f, -28.1875f, 21.2500f, 24, 29}, // 0424 - {0.281250f, 0.425781f, 0.291992f, 0.539063f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0425 - {0.323730f, 0.285156f, 0.333984f, 0.421875f, 3.2500f, -28.2500f, 22.1875f, 21, 35}, // 0426 - {0.230469f, 0.542969f, 0.240234f, 0.656250f, 0.1875f, -28.1875f, 20.3125f, 20, 29}, // 0427 - {0.892090f, 0.101563f, 0.906738f, 0.214844f, 0.1875f, -28.1875f, 30.1250f, 30, 29}, // 0428 - {0.520508f, 0.000000f, 0.536621f, 0.136719f, 0.1875f, -28.2500f, 31.6875f, 33, 35}, // 0429 - {0.211914f, 0.367188f, 0.223633f, 0.480469f, -1.8750f, -28.1875f, 21.2500f, 24, 29}, // 042a - {0.676270f, 0.128906f, 0.689941f, 0.242188f, 0.2500f, -28.1875f, 25.3750f, 28, 29}, // 042b - {0.240723f, 0.542969f, 0.250488f, 0.656250f, 0.2500f, -28.1875f, 18.5625f, 20, 29}, // 042c - {0.250977f, 0.542969f, 0.260742f, 0.656250f, 0.0000f, -28.5625f, 19.2500f, 20, 29}, // 042d - {0.583496f, 0.136719f, 0.597168f, 0.250000f, 0.6250f, -28.5625f, 27.1875f, 28, 29}, // 042e - {0.261230f, 0.542969f, 0.270996f, 0.656250f, -1.8125f, -28.1875f, 17.4375f, 20, 29}, // 042f - {0.446777f, 0.765625f, 0.455566f, 0.855469f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0430 - {0.108887f, 0.511719f, 0.118164f, 0.632813f, -0.7500f, -29.8125f, 16.5000f, 19, 31}, // 0431 - {0.498535f, 0.773438f, 0.507324f, 0.859375f, 0.0625f, -22.0000f, 16.6875f, 18, 22}, // 0432 - {0.494141f, 0.195313f, 0.501465f, 0.281250f, -0.0625f, -22.0000f, 12.4375f, 15, 22}, // 0433 - {0.796875f, 0.511719f, 0.807129f, 0.621094f, -0.8750f, -22.0000f, 19.1250f, 21, 28}, // 0434 - {0.679688f, 0.765625f, 0.688477f, 0.855469f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0435 - {0.322754f, 0.542969f, 0.335449f, 0.628906f, -1.6250f, -22.0000f, 22.6875f, 26, 22}, // 0436 - {0.619629f, 0.769531f, 0.628418f, 0.859375f, -0.5000f, -22.3125f, 16.2500f, 18, 23}, // 0437 - {0.698730f, 0.792969f, 0.707031f, 0.878906f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 0438 - {0.029297f, 0.703125f, 0.037598f, 0.820313f, -0.0625f, -29.4375f, 16.8125f, 17, 30}, // 0439 - {0.532715f, 0.773438f, 0.541504f, 0.859375f, 0.1250f, -22.0000f, 16.5000f, 18, 22}, // 043a - {0.063477f, 0.761719f, 0.072754f, 0.847656f, -1.6250f, -22.0000f, 16.5000f, 19, 22}, // 043b - {0.187012f, 0.718750f, 0.197754f, 0.804688f, 0.1250f, -22.0000f, 22.1875f, 22, 22}, // 043c - {0.707520f, 0.792969f, 0.715820f, 0.878906f, -0.0625f, -22.0000f, 16.7500f, 17, 22}, // 043d - {0.724121f, 0.734375f, 0.733398f, 0.824219f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 043e - {0.816406f, 0.792969f, 0.824707f, 0.878906f, -0.0625f, -22.0000f, 16.8125f, 17, 22}, // 043f - {0.169922f, 0.632813f, 0.178711f, 0.750000f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0440 - {0.283691f, 0.777344f, 0.291992f, 0.867188f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0441 - {0.566895f, 0.773438f, 0.575684f, 0.859375f, -1.0625f, -21.9375f, 15.3125f, 18, 22}, // 0442 - {0.817383f, 0.550781f, 0.826660f, 0.667969f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0443 - {0.662109f, 0.000000f, 0.675781f, 0.144531f, -0.7500f, -29.8750f, 26.0625f, 28, 37}, // 0444 - {0.834961f, 0.773438f, 0.843750f, 0.859375f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0445 - {0.108398f, 0.636719f, 0.117676f, 0.746094f, -0.0625f, -22.0000f, 17.8125f, 19, 28}, // 0446 - {0.406738f, 0.800781f, 0.415039f, 0.886719f, -0.1875f, -22.0000f, 16.4375f, 17, 22}, // 0447 - {0.041992f, 0.613281f, 0.054199f, 0.699219f, -0.0625f, -22.0000f, 24.0625f, 25, 22}, // 0448 - {0.635742f, 0.285156f, 0.648926f, 0.390625f, -0.0625f, -22.0000f, 25.7500f, 27, 27}, // 0449 - {0.198242f, 0.718750f, 0.208984f, 0.804688f, -1.5000f, -22.0000f, 18.6875f, 22, 22}, // 044a - {0.335938f, 0.542969f, 0.348633f, 0.628906f, 0.5000f, -22.0000f, 23.8750f, 26, 22}, // 044b - {0.220703f, 0.777344f, 0.229492f, 0.863281f, 0.1250f, -22.0000f, 16.3125f, 18, 22}, // 044c - {0.292480f, 0.777344f, 0.300781f, 0.867188f, -0.6875f, -22.2500f, 15.6250f, 17, 23}, // 044d - {0.586914f, 0.503906f, 0.599609f, 0.593750f, 0.1875f, -22.2500f, 24.0000f, 26, 23}, // 044e - {0.229980f, 0.777344f, 0.238770f, 0.863281f, -0.9375f, -22.0000f, 16.7500f, 18, 22}, // 044f - {0.661621f, 0.593750f, 0.670410f, 0.714844f, -0.7500f, -29.6875f, 15.5000f, 18, 31}, // 0450 - {0.290527f, 0.660156f, 0.299316f, 0.773438f, -0.7500f, -28.5625f, 15.5000f, 18, 29}, // 0451 - {0.567871f, 0.152344f, 0.577637f, 0.300781f, -2.7500f, -29.9375f, 16.6875f, 20, 38}, // 0452 - {0.475098f, 0.726563f, 0.482422f, 0.843750f, -0.0625f, -29.3125f, 12.4375f, 15, 30}, // 0453 - {0.301270f, 0.777344f, 0.309570f, 0.867188f, -0.7500f, -22.2500f, 15.6875f, 17, 23}, // 0454 - {0.310059f, 0.777344f, 0.318359f, 0.867188f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0455 - {0.918457f, 0.808594f, 0.922363f, 0.925781f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0456 - {0.925781f, 0.738281f, 0.933105f, 0.851563f, -3.4375f, -28.2500f, 7.8125f, 15, 29}, // 0457 - {0.889648f, 0.750000f, 0.895020f, 0.898438f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 0458 - {0.010254f, 0.476563f, 0.023926f, 0.562500f, -1.3125f, -22.0000f, 25.5000f, 28, 22}, // 0459 - {0.666016f, 0.503906f, 0.679199f, 0.589844f, -0.0625f, -22.0000f, 25.5625f, 27, 22}, // 045a - {0.010254f, 0.566406f, 0.019531f, 0.683594f, -1.8750f, -29.9375f, 16.8125f, 19, 30}, // 045b - {0.322754f, 0.632813f, 0.331543f, 0.750000f, 0.1250f, -29.2500f, 16.5000f, 18, 30}, // 045c - {0.038086f, 0.703125f, 0.046387f, 0.820313f, -0.0625f, -29.3750f, 16.8125f, 17, 30}, // 045d - {0.736816f, 0.347656f, 0.746094f, 0.492188f, -1.6875f, -29.4375f, 15.0000f, 19, 37}, // 045e - {0.589355f, 0.253906f, 0.597656f, 0.363281f, -0.0625f, -22.0000f, 16.8125f, 17, 28}, // 045f - {0.921875f, 0.117188f, 0.936035f, 0.230469f, -0.3750f, -28.5000f, 28.0625f, 29, 29}, // 0460 - {0.895996f, 0.640625f, 0.907715f, 0.726563f, -1.5000f, -22.0000f, 20.6875f, 24, 22}, // 0461 - {0.292480f, 0.425781f, 0.303223f, 0.539063f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 0462 - {0.866699f, 0.496094f, 0.876465f, 0.613281f, -2.1875f, -30.0000f, 16.3125f, 20, 30}, // 0463 - {0.531738f, 0.140625f, 0.544922f, 0.253906f, 0.6250f, -28.5625f, 26.3750f, 27, 29}, // 0464 - {0.913574f, 0.593750f, 0.925293f, 0.683594f, 0.1250f, -22.2500f, 22.1250f, 24, 23}, // 0465 - {0.696289f, 0.378906f, 0.707520f, 0.492188f, -1.5000f, -28.1875f, 18.5625f, 23, 29}, // 0466 - {0.895996f, 0.730469f, 0.905762f, 0.816406f, -1.7500f, -22.0000f, 16.1875f, 20, 22}, // 0467 - {0.936523f, 0.117188f, 0.950684f, 0.230469f, 0.9375f, -28.1875f, 26.8125f, 29, 29}, // 0468 - {0.358398f, 0.613281f, 0.370605f, 0.699219f, 0.7500f, -22.0000f, 23.0000f, 25, 22}, // 0469 - {0.185059f, 0.250000f, 0.197754f, 0.363281f, 0.0000f, -28.1250f, 25.3750f, 26, 29}, // 046a - {0.209473f, 0.718750f, 0.220215f, 0.804688f, -0.0625f, -22.0000f, 21.6250f, 22, 22}, // 046b - {0.707031f, 0.000000f, 0.724121f, 0.113281f, 0.5625f, -28.1250f, 33.6250f, 35, 29}, // 046c - {0.641602f, 0.406250f, 0.656250f, 0.492188f, 0.1875f, -22.0000f, 29.1875f, 30, 22}, // 046d - {0.961914f, 0.195313f, 0.970215f, 0.363281f, -1.2500f, -35.6250f, 15.3125f, 17, 43}, // 046e - {0.357910f, 0.429688f, 0.366211f, 0.574219f, -1.1250f, -29.8750f, 14.6250f, 17, 37}, // 046f - {0.746582f, 0.378906f, 0.757813f, 0.492188f, -0.8125f, -28.1875f, 20.9375f, 23, 29}, // 0470 - {0.428223f, 0.371094f, 0.439453f, 0.488281f, -0.7500f, -22.0000f, 21.3125f, 23, 30}, // 0471 - {0.726563f, 0.496094f, 0.736816f, 0.609375f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 0472 - {0.733887f, 0.734375f, 0.743164f, 0.824219f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 0473 - {0.870605f, 0.378906f, 0.881836f, 0.492188f, -1.6875f, -28.5625f, 18.8125f, 23, 29}, // 0474 - {0.860840f, 0.738281f, 0.870117f, 0.828125f, -1.5000f, -22.2500f, 15.0000f, 19, 23}, // 0475 - {0.768555f, 0.136719f, 0.779785f, 0.273438f, -1.6875f, -34.9375f, 18.8125f, 23, 35}, // 0476 - {0.983398f, 0.472656f, 0.993164f, 0.593750f, -2.2500f, -30.1250f, 15.0000f, 20, 31}, // 0477 - {0.501465f, 0.000000f, 0.520020f, 0.140625f, -0.3750f, -28.5625f, 35.1875f, 38, 36}, // 0478 - {0.615234f, 0.000000f, 0.632324f, 0.117188f, -0.7500f, -22.3125f, 31.7500f, 35, 30}, // 0479 - {0.958984f, 0.367188f, 0.969238f, 0.496094f, -0.3750f, -30.3750f, 20.2500f, 21, 33}, // 047a - {0.532227f, 0.664063f, 0.541504f, 0.769531f, -0.7500f, -24.0625f, 16.7500f, 19, 27}, // 047b - {0.568848f, 0.000000f, 0.583008f, 0.148438f, -0.3750f, -37.2500f, 28.0625f, 29, 38}, // 047c - {0.437012f, 0.121094f, 0.449707f, 0.246094f, -0.4375f, -31.3125f, 24.0625f, 26, 32}, // 047d - {0.724609f, 0.000000f, 0.738770f, 0.136719f, -0.3750f, -33.7500f, 28.0625f, 29, 35}, // 047e - {0.224121f, 0.367188f, 0.235840f, 0.480469f, -1.5000f, -28.5625f, 20.6875f, 24, 29}, // 047f - {0.589355f, 0.363281f, 0.599121f, 0.500000f, -0.3750f, -28.5625f, 18.8125f, 20, 35}, // 0480 - {0.397949f, 0.714844f, 0.406250f, 0.828125f, -0.5625f, -22.3125f, 15.8125f, 17, 29}, // 0481 - {0.332031f, 0.632813f, 0.341797f, 0.738281f, -0.3125f, -26.3125f, 18.4375f, 20, 27}, // 0482 - {0.758789f, 0.527344f, 0.766113f, 0.566406f, 0.1250f, -29.4375f, 14.5625f, 15, 10}, // 0483 - {0.358398f, 0.578125f, 0.365723f, 0.613281f, 0.4375f, -29.8750f, 15.2500f, 15, 9}, // 0484 - {0.896973f, 0.363281f, 0.900879f, 0.402344f, 0.6250f, -31.1250f, 8.6875f, 8, 10}, // 0485 - {0.866699f, 0.394531f, 0.870605f, 0.433594f, 0.6875f, -31.1250f, 9.1875f, 8, 10}, // 0486 - {0.856934f, 0.285156f, 0.870117f, 0.390625f, 1.7500f, -24.5000f, 30.0000f, 27, 27}, // 0487 - {0.583496f, 0.000000f, 0.599121f, 0.132813f, -1.0625f, -28.1875f, 29.7500f, 32, 34}, // 0488 - {0.553223f, 0.000000f, 0.568359f, 0.140625f, -0.8125f, -28.5625f, 28.8125f, 31, 36}, // 0489 - {0.788086f, 0.000000f, 0.799805f, 0.160156f, 0.2500f, -35.1250f, 20.7500f, 24, 41}, // 048a - {0.599609f, 0.363281f, 0.609375f, 0.500000f, -0.0625f, -29.4375f, 16.7500f, 20, 35}, // 048b - {0.303711f, 0.425781f, 0.314453f, 0.539063f, -2.1250f, -28.1875f, 18.5625f, 22, 29}, // 048c - {0.638184f, 0.734375f, 0.647949f, 0.820313f, -2.4375f, -22.0000f, 16.3125f, 20, 22}, // 048d - {0.271484f, 0.542969f, 0.281250f, 0.656250f, 0.1875f, -28.1875f, 18.6250f, 20, 29}, // 048e - {0.522949f, 0.632813f, 0.531738f, 0.750000f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 048f - {0.515625f, 0.441406f, 0.524414f, 0.578125f, 0.2500f, -34.1250f, 16.3750f, 18, 35}, // 0490 - {0.592773f, 0.750000f, 0.600098f, 0.859375f, -0.0625f, -27.4375f, 13.5000f, 15, 28}, // 0491 - {0.281738f, 0.542969f, 0.291504f, 0.656250f, -2.0625f, -28.1250f, 16.3750f, 20, 29}, // 0492 - {0.415527f, 0.800781f, 0.423828f, 0.886719f, -2.3125f, -22.0000f, 12.4375f, 17, 22}, // 0493 - {0.291992f, 0.542969f, 0.301758f, 0.656250f, 0.2500f, -28.1875f, 17.1250f, 20, 29}, // 0494 - {0.987793f, 0.714844f, 0.996582f, 0.820313f, -0.0625f, -22.0000f, 16.3125f, 18, 27}, // 0495 - {0.599609f, 0.000000f, 0.614746f, 0.136719f, -1.6875f, -28.1875f, 25.5625f, 31, 35}, // 0496 - {0.732422f, 0.234375f, 0.745605f, 0.343750f, -1.6250f, -22.0000f, 22.6875f, 27, 28}, // 0497 - {0.746094f, 0.234375f, 0.756348f, 0.375000f, -0.3750f, -28.5000f, 19.6875f, 21, 36}, // 0498 - {0.074707f, 0.636719f, 0.083496f, 0.753906f, -0.5000f, -22.2500f, 16.2500f, 18, 30}, // 0499 - {0.649414f, 0.144531f, 0.660156f, 0.281250f, 0.3125f, -28.1875f, 18.8125f, 22, 35}, // 049a - {0.886230f, 0.636719f, 0.895508f, 0.746094f, 0.1250f, -22.0000f, 16.5000f, 19, 28}, // 049b - {0.737305f, 0.496094f, 0.747559f, 0.609375f, 0.2500f, -28.1875f, 19.0625f, 21, 29}, // 049c - {0.488770f, 0.761719f, 0.498047f, 0.847656f, 0.1250f, -22.0000f, 16.6250f, 19, 22}, // 049d - {0.790527f, 0.367188f, 0.802246f, 0.480469f, -2.8125f, -28.1875f, 18.8125f, 24, 29}, // 049e - {0.562988f, 0.449219f, 0.573242f, 0.566406f, -2.9375f, -29.9375f, 15.5000f, 21, 30}, // 049f - {0.422363f, 0.121094f, 0.436523f, 0.234375f, -0.7500f, -28.1875f, 25.1875f, 29, 29}, // 04a0 - {0.524902f, 0.542969f, 0.537598f, 0.628906f, -1.0000f, -21.9375f, 21.5625f, 26, 22}, // 04a1 - {0.827637f, 0.136719f, 0.838867f, 0.273438f, 0.3125f, -28.1875f, 20.8125f, 23, 35}, // 04a2 - {0.758789f, 0.566406f, 0.768555f, 0.675781f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04a3 - {0.800293f, 0.105469f, 0.814941f, 0.218750f, 0.3125f, -28.1875f, 28.8750f, 30, 29}, // 04a4 - {0.657715f, 0.718750f, 0.668457f, 0.804688f, -0.0625f, -22.0000f, 21.0000f, 22, 22}, // 04a5 - {0.926270f, 0.000000f, 0.941406f, 0.113281f, 0.2500f, -28.1875f, 30.1875f, 31, 29}, // 04a6 - {0.597656f, 0.140625f, 0.612305f, 0.242188f, -0.0625f, -22.0000f, 25.6250f, 30, 26}, // 04a7 - {0.314941f, 0.425781f, 0.325684f, 0.539063f, -0.3750f, -28.4375f, 20.6875f, 22, 29}, // 04a8 - {0.093750f, 0.742188f, 0.103027f, 0.832031f, -0.7500f, -22.1875f, 16.8750f, 19, 23}, // 04a9 - {0.156250f, 0.335938f, 0.166016f, 0.476563f, -0.3125f, -28.5625f, 18.8125f, 20, 36}, // 04aa - {0.351074f, 0.703125f, 0.359375f, 0.820313f, -0.7500f, -22.3125f, 15.4375f, 17, 30}, // 04ab - {0.334473f, 0.285156f, 0.344727f, 0.421875f, -1.3750f, -28.1875f, 17.3125f, 21, 35}, // 04ac - {0.507813f, 0.707031f, 0.516602f, 0.816406f, -1.0625f, -22.0000f, 15.3125f, 18, 28}, // 04ad - {0.326172f, 0.425781f, 0.336914f, 0.539063f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 04ae - {0.779297f, 0.601563f, 0.788574f, 0.714844f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04af - {0.337402f, 0.425781f, 0.348145f, 0.539063f, -1.5625f, -28.1875f, 18.7500f, 22, 29}, // 04b0 - {0.951660f, 0.605469f, 0.960938f, 0.718750f, -1.5000f, -22.0000f, 15.0000f, 19, 29}, // 04b1 - {0.862305f, 0.144531f, 0.873047f, 0.281250f, -1.2500f, -28.1875f, 18.6875f, 22, 35}, // 04b2 - {0.083984f, 0.640625f, 0.093262f, 0.750000f, -1.4375f, -22.0000f, 15.0000f, 19, 28}, // 04b3 - {0.537109f, 0.000000f, 0.552734f, 0.136719f, -1.2500f, -28.1875f, 26.3750f, 32, 35}, // 04b4 - {0.896973f, 0.406250f, 0.908203f, 0.515625f, -1.3125f, -22.0000f, 20.4375f, 23, 28}, // 04b5 - {0.839355f, 0.136719f, 0.850586f, 0.273438f, 0.1875f, -28.1875f, 20.3125f, 23, 35}, // 04b6 - {0.769043f, 0.566406f, 0.778809f, 0.675781f, -0.1875f, -22.0000f, 16.5000f, 20, 28}, // 04b7 - {0.302246f, 0.542969f, 0.312012f, 0.656250f, 0.1875f, -28.1875f, 20.1250f, 20, 29}, // 04b8 - {0.757324f, 0.800781f, 0.765625f, 0.886719f, -0.1875f, -22.0000f, 16.5000f, 17, 22}, // 04b9 - {0.312500f, 0.542969f, 0.322266f, 0.656250f, 2.6875f, -28.1875f, 20.3750f, 20, 29}, // 04ba - {0.766113f, 0.800781f, 0.774414f, 0.886719f, 2.3125f, -22.0625f, 16.5625f, 17, 22}, // 04bb - {0.198242f, 0.250000f, 0.210938f, 0.363281f, -1.5625f, -28.5000f, 24.6250f, 26, 29}, // 04bc - {0.668945f, 0.718750f, 0.679199f, 0.808594f, -2.5625f, -22.2500f, 17.6250f, 21, 23}, // 04bd - {0.862793f, 0.000000f, 0.875488f, 0.140625f, -1.5625f, -28.5000f, 24.6250f, 26, 36}, // 04be - {0.386719f, 0.457031f, 0.396973f, 0.574219f, -2.5625f, -22.3125f, 17.6250f, 21, 30}, // 04bf - {0.547852f, 0.816406f, 0.551758f, 0.929688f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04c0 - {0.647461f, 0.000000f, 0.661621f, 0.140625f, -1.6875f, -35.1250f, 25.6250f, 29, 36}, // 04c1 - {0.690430f, 0.140625f, 0.703125f, 0.257813f, -1.6250f, -29.4375f, 22.6875f, 26, 30}, // 04c2 - {0.000000f, 0.476563f, 0.009766f, 0.597656f, 0.2500f, -28.1875f, 18.6875f, 20, 31}, // 04c3 - {0.000000f, 0.718750f, 0.008789f, 0.824219f, 0.1250f, -22.0000f, 16.5000f, 18, 27}, // 04c4 - {0.985352f, 0.054688f, 0.997559f, 0.187500f, -1.2500f, -28.1875f, 20.8125f, 25, 34}, // 04c5 - {0.024414f, 0.476563f, 0.035156f, 0.585938f, -1.6250f, -22.0000f, 16.5000f, 22, 28}, // 04c6 - {0.756836f, 0.234375f, 0.767090f, 0.375000f, 0.2500f, -28.1875f, 20.8125f, 21, 36}, // 04c7 - {0.359863f, 0.703125f, 0.368164f, 0.820313f, -0.0625f, -22.0000f, 16.7500f, 17, 30}, // 04c8 - {0.815430f, 0.125000f, 0.827148f, 0.257813f, 0.3125f, -28.1875f, 20.8125f, 24, 34}, // 04c9 - {0.966797f, 0.566406f, 0.976563f, 0.675781f, -0.0625f, -22.0000f, 16.7500f, 20, 28}, // 04ca - {0.672363f, 0.363281f, 0.682129f, 0.500000f, 0.1875f, -28.1875f, 20.3125f, 20, 35}, // 04cb - {0.873047f, 0.718750f, 0.881348f, 0.828125f, -0.1875f, -22.0000f, 16.4375f, 17, 28}, // 04cc - {0.834473f, 0.000000f, 0.848145f, 0.132813f, 0.1875f, -28.1875f, 24.8125f, 28, 34}, // 04cd - {0.884277f, 0.363281f, 0.896484f, 0.472656f, 0.1250f, -22.0000f, 22.1875f, 25, 28}, // 04ce - {0.552246f, 0.816406f, 0.556152f, 0.929688f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 04cf - {0.354492f, 0.140625f, 0.365234f, 0.281250f, -1.5000f, -35.1250f, 18.7500f, 22, 36}, // 04d0 - {0.670898f, 0.593750f, 0.679688f, 0.714844f, -0.7500f, -29.7500f, 16.0625f, 18, 31}, // 04d1 - {0.812500f, 0.261719f, 0.823242f, 0.394531f, -1.5000f, -33.9375f, 18.7500f, 22, 34}, // 04d2 - {0.299805f, 0.660156f, 0.308594f, 0.773438f, -0.7500f, -28.5625f, 16.0625f, 18, 29}, // 04d3 - {0.941895f, 0.000000f, 0.957031f, 0.113281f, -1.6875f, -28.1875f, 28.2500f, 31, 29}, // 04d4 - {0.969727f, 0.472656f, 0.982910f, 0.562500f, -0.6250f, -22.2500f, 25.6250f, 27, 23}, // 04d5 - {0.821777f, 0.406250f, 0.830566f, 0.546875f, 0.3125f, -35.1250f, 16.4375f, 18, 36}, // 04d6 - {0.876953f, 0.593750f, 0.885742f, 0.714844f, -0.7500f, -29.7500f, 15.5000f, 18, 31}, // 04d7 - {0.504395f, 0.425781f, 0.515137f, 0.539063f, -0.6250f, -28.5000f, 21.1875f, 22, 29}, // 04d8 - {0.628906f, 0.769531f, 0.637695f, 0.859375f, 2.2500f, -22.3750f, 15.7500f, 18, 23}, // 04d9 - {0.440430f, 0.265625f, 0.451172f, 0.398438f, -0.6250f, -33.1250f, 21.1875f, 22, 34}, // 04da - {0.118652f, 0.609375f, 0.127930f, 0.722656f, 0.8750f, -28.6250f, 15.7500f, 19, 29}, // 04db - {0.773438f, 0.000000f, 0.787598f, 0.132813f, -1.6875f, -33.9375f, 25.6250f, 29, 34}, // 04dc - {0.211426f, 0.250000f, 0.224121f, 0.363281f, -1.6250f, -28.2500f, 22.6875f, 26, 29}, // 04dd - {0.345215f, 0.285156f, 0.355469f, 0.421875f, -0.3750f, -34.2500f, 19.6875f, 21, 35}, // 04de - {0.309082f, 0.660156f, 0.317871f, 0.773438f, -0.5000f, -28.5625f, 16.2500f, 18, 29}, // 04df - {0.428223f, 0.609375f, 0.437500f, 0.722656f, -0.5000f, -28.1250f, 17.1875f, 19, 29}, // 04e0 - {0.469238f, 0.609375f, 0.478516f, 0.722656f, -0.5000f, -22.0000f, 17.1875f, 19, 29}, // 04e1 - {0.472656f, 0.335938f, 0.482910f, 0.468750f, 0.2500f, -33.6250f, 20.7500f, 21, 34}, // 04e2 - {0.951172f, 0.722656f, 0.959473f, 0.832031f, -0.0625f, -27.9375f, 16.8125f, 17, 28}, // 04e3 - {0.980957f, 0.335938f, 0.991211f, 0.468750f, 0.2500f, -33.9375f, 20.7500f, 21, 34}, // 04e4 - {0.583984f, 0.714844f, 0.592285f, 0.828125f, -0.0625f, -28.2500f, 16.8125f, 17, 29}, // 04e5 - {0.512207f, 0.285156f, 0.522461f, 0.421875f, -0.3750f, -34.2500f, 20.1875f, 21, 35}, // 04e6 - {0.479004f, 0.609375f, 0.488281f, 0.722656f, -0.7500f, -28.5625f, 16.7500f, 19, 29}, // 04e7 - {0.748047f, 0.496094f, 0.758301f, 0.609375f, -0.3750f, -28.5625f, 20.2500f, 21, 29}, // 04e8 - {0.332031f, 0.742188f, 0.341309f, 0.832031f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 04e9 - {0.542969f, 0.285156f, 0.553223f, 0.421875f, -0.3750f, -33.8125f, 20.2500f, 21, 35}, // 04ea - {0.459473f, 0.566406f, 0.468750f, 0.683594f, -0.7500f, -29.0000f, 16.7500f, 19, 30}, // 04eb - {0.177246f, 0.367188f, 0.187012f, 0.503906f, 0.0000f, -34.3125f, 19.2500f, 20, 35}, // 04ec - {0.970215f, 0.714844f, 0.978516f, 0.828125f, -0.6875f, -28.5625f, 15.6250f, 17, 29}, // 04ed - {0.610840f, 0.265625f, 0.621582f, 0.398438f, -1.3125f, -33.6250f, 18.8750f, 22, 34}, // 04ee - {0.079102f, 0.375000f, 0.088379f, 0.515625f, -1.6875f, -28.0000f, 15.0000f, 19, 36}, // 04ef - {0.660645f, 0.148438f, 0.671387f, 0.285156f, -1.3125f, -33.9375f, 18.9375f, 22, 35}, // 04f0 - {0.088867f, 0.375000f, 0.098145f, 0.515625f, -1.6875f, -28.2500f, 15.0625f, 19, 36}, // 04f1 - {0.520508f, 0.140625f, 0.531250f, 0.281250f, -1.3125f, -35.0000f, 18.8750f, 22, 36}, // 04f2 - {0.926758f, 0.351563f, 0.936035f, 0.496094f, -1.6875f, -29.3750f, 15.0000f, 19, 37}, // 04f3 - {0.109863f, 0.375000f, 0.119629f, 0.507813f, 0.1875f, -33.9375f, 20.3125f, 20, 34}, // 04f4 - {0.979004f, 0.714844f, 0.987305f, 0.828125f, -0.1875f, -28.2500f, 16.4375f, 17, 29}, // 04f5 - {0.397461f, 0.457031f, 0.406250f, 0.593750f, 0.1875f, -28.1875f, 16.3125f, 18, 35}, // 04f6 - {0.881836f, 0.750000f, 0.889160f, 0.859375f, -0.0625f, -22.0000f, 12.4375f, 15, 28}, // 04f7 - {0.848633f, 0.000000f, 0.862305f, 0.132813f, 0.2500f, -33.9375f, 25.3750f, 28, 34}, // 04f8 - {0.224609f, 0.250000f, 0.237305f, 0.363281f, 0.5000f, -28.2500f, 23.8750f, 26, 29}, // 04f9 - {0.873535f, 0.234375f, 0.883789f, 0.375000f, -1.1250f, -28.1875f, 17.6250f, 21, 36}, // 04fa - {0.380371f, 0.703125f, 0.388672f, 0.820313f, -1.1875f, -22.0000f, 12.3750f, 17, 30}, // 04fb - {0.615234f, 0.121094f, 0.626465f, 0.261719f, -1.2500f, -28.1875f, 18.7500f, 23, 36}, // 04fc - {0.098633f, 0.500000f, 0.108398f, 0.617188f, -1.4375f, -22.0000f, 15.0000f, 20, 30}, // 04fd - {0.541504f, 0.425781f, 0.552246f, 0.539063f, -1.3125f, -28.1875f, 18.6875f, 22, 29}, // 04fe - {0.239258f, 0.777344f, 0.248047f, 0.863281f, -1.4375f, -22.0000f, 15.0625f, 18, 22}, // 04ff -// RANGE: 0x2121 - 0x2123, start 0x257 - {0.406250f, 0.613281f, 0.422852f, 0.675781f, 1.0000f, -23.5000f, 35.1875f, 34, 16}, // 2121 - {0.791016f, 0.164063f, 0.800293f, 0.214844f, -0.5000f, -28.1875f, 18.5625f, 19, 13}, // 2122 -// RANGE: 0xfffd - 0xfffe, start 0x259 - {0.485352f, 0.000000f, 0.500977f, 0.191406f, -0.6250f, -39.6875f, 30.1875f, 32, 49}, // fffd +// RANGE: 0x20 - 0x80, start 0x21 + {0.000000f, 0.000000f, 0.001953f, 0.001953f, -2.0000f, -4.0000f, 7.5000f, 1, 1}, // 0020 + {0.888672f, 0.689453f, 0.904297f, 0.746094f, 0.2500f, -28.1875f, 7.8750f, 8, 29}, // 0021 + {0.751953f, 0.699219f, 0.775391f, 0.724609f, 0.1875f, -28.1875f, 11.6875f, 12, 13}, // 0022 + {0.791016f, 0.582031f, 0.830078f, 0.638672f, -1.0625f, -28.1875f, 18.0000f, 20, 29}, // 0023 + {0.212891f, 0.250000f, 0.248047f, 0.320313f, -0.2500f, -32.0000f, 17.3125f, 18, 36}, // 0024 + {0.498047f, 0.560547f, 0.544922f, 0.617188f, -0.3750f, -28.5000f, 22.6875f, 24, 29}, // 0025 + {0.546875f, 0.564453f, 0.589844f, 0.621094f, -0.8750f, -28.5000f, 19.7500f, 22, 29}, // 0026 + {0.166016f, 0.701172f, 0.181641f, 0.726563f, -0.1875f, -28.1875f, 6.8125f, 8, 13}, // 0027 + {0.607422f, 0.623047f, 0.630859f, 0.699219f, -0.0625f, -31.0000f, 10.0625f, 12, 39}, // 0028 + {0.460938f, 0.660156f, 0.484375f, 0.736328f, -1.6250f, -31.0000f, 10.1250f, 12, 39}, // 0029 + {0.341797f, 0.576172f, 0.371094f, 0.607422f, -0.8750f, -21.9375f, 13.1875f, 15, 16}, // 002a + {0.263672f, 0.494141f, 0.300781f, 0.537109f, -0.8750f, -24.0625f, 17.2500f, 19, 22}, // 002b + {0.146484f, 0.701172f, 0.164063f, 0.726563f, -1.0625f, -7.5625f, 6.8750f, 9, 13}, // 002c + {0.677734f, 0.619141f, 0.703125f, 0.632813f, 0.2500f, -15.5625f, 13.0625f, 13, 7}, // 002d + {0.605469f, 0.701172f, 0.621094f, 0.716797f, 0.3125f, -7.3750f, 8.3125f, 8, 8}, // 002e + {0.964844f, 0.230469f, 0.996094f, 0.291016f, -1.8750f, -28.2500f, 12.1250f, 16, 31}, // 002f + {0.000000f, 0.625000f, 0.037109f, 0.681641f, -0.3125f, -28.5000f, 17.5625f, 19, 29}, // 0030 + {0.861328f, 0.689453f, 0.886719f, 0.746094f, 1.0625f, -28.5625f, 17.5625f, 13, 29}, // 0031 + {0.039063f, 0.625000f, 0.076172f, 0.681641f, -0.2500f, -28.5000f, 17.5000f, 19, 29}, // 0032 + {0.832031f, 0.630859f, 0.869141f, 0.687500f, -0.3750f, -28.5000f, 17.5000f, 19, 29}, // 0033 + {0.447266f, 0.601563f, 0.486328f, 0.658203f, -0.8750f, -28.1875f, 17.5625f, 20, 29}, // 0034 + {0.751953f, 0.640625f, 0.787109f, 0.697266f, 0.1250f, -28.1875f, 17.5000f, 18, 29}, // 0035 + {0.871094f, 0.630859f, 0.908203f, 0.687500f, -0.0625f, -28.5000f, 17.5625f, 19, 29}, // 0036 + {0.212891f, 0.634766f, 0.250000f, 0.691406f, -0.6250f, -28.1875f, 17.5625f, 19, 29}, // 0037 + {0.251953f, 0.634766f, 0.289063f, 0.691406f, -0.5000f, -28.5000f, 17.5625f, 19, 29}, // 0038 + {0.291016f, 0.634766f, 0.328125f, 0.691406f, -0.5625f, -28.5000f, 17.5000f, 19, 29}, // 0039 + {0.128906f, 0.697266f, 0.144531f, 0.740234f, 0.3125f, -21.9375f, 7.9375f, 8, 22}, // 003a + {0.636719f, 0.564453f, 0.654297f, 0.617188f, -0.1875f, -21.9375f, 7.8750f, 9, 27}, // 003b + {0.742188f, 0.167969f, 0.773438f, 0.207031f, -1.0000f, -20.6875f, 15.1250f, 16, 20}, // 003c + {0.269531f, 0.693359f, 0.302734f, 0.720703f, 0.1875f, -20.1250f, 16.9375f, 17, 14}, // 003d + {0.707031f, 0.167969f, 0.740234f, 0.207031f, -0.1250f, -20.5000f, 15.3750f, 17, 20}, // 003e + {0.964844f, 0.355469f, 0.998047f, 0.412109f, -1.2500f, -28.5625f, 14.3750f, 17, 29}, // 003f + {0.865234f, 0.558594f, 0.921875f, 0.628906f, -0.5000f, -27.6250f, 27.5625f, 29, 36}, // 0040 + {0.591797f, 0.564453f, 0.634766f, 0.621094f, -1.5000f, -28.2500f, 18.6875f, 22, 29}, // 0041 + {0.341797f, 0.613281f, 0.380859f, 0.669922f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0042 + {0.382813f, 0.613281f, 0.421875f, 0.669922f, -0.3125f, -28.5000f, 18.8125f, 20, 29}, // 0043 + {0.923828f, 0.617188f, 0.962891f, 0.673828f, 0.3125f, -28.1875f, 19.8125f, 20, 29}, // 0044 + {0.789063f, 0.640625f, 0.824219f, 0.697266f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0045 + {0.423828f, 0.660156f, 0.458984f, 0.716797f, 0.3125f, -28.1875f, 16.4375f, 18, 29}, // 0046 + {0.212891f, 0.576172f, 0.253906f, 0.632813f, -0.3125f, -28.5000f, 19.8750f, 21, 29}, // 0047 + {0.255859f, 0.576172f, 0.296875f, 0.632813f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 0048 + {0.304688f, 0.693359f, 0.320313f, 0.750000f, 0.6250f, -28.1875f, 8.6250f, 8, 29}, // 0049 + {0.330078f, 0.671875f, 0.365234f, 0.728516f, -1.1250f, -28.1875f, 16.3125f, 18, 29}, // 004a + {0.298828f, 0.576172f, 0.339844f, 0.632813f, 0.3125f, -28.1875f, 18.8125f, 21, 29}, // 004b + {0.367188f, 0.671875f, 0.402344f, 0.728516f, 0.3125f, -28.1875f, 16.3750f, 18, 29}, // 004c + {0.447266f, 0.542969f, 0.496094f, 0.599609f, 0.1875f, -28.1875f, 24.7500f, 25, 29}, // 004d + {0.089844f, 0.578125f, 0.130859f, 0.634766f, 0.3125f, -28.1875f, 20.8125f, 21, 29}, // 004e + {0.132813f, 0.578125f, 0.173828f, 0.634766f, -0.3750f, -28.5625f, 20.1875f, 21, 29}, // 004f + {0.488281f, 0.619141f, 0.527344f, 0.675781f, 0.3125f, -28.1875f, 18.7500f, 20, 29}, // 0050 + {0.953125f, 0.105469f, 0.998047f, 0.167969f, -0.3750f, -28.5625f, 20.6250f, 23, 32}, // 0051 + {0.636719f, 0.619141f, 0.675781f, 0.675781f, 0.3125f, -28.1875f, 18.9375f, 20, 29}, // 0052 + {0.529297f, 0.623047f, 0.568359f, 0.679688f, -0.5625f, -28.5000f, 18.1250f, 20, 29}, // 0053 + {0.705078f, 0.582031f, 0.746094f, 0.638672f, -1.3750f, -28.1875f, 17.3125f, 21, 29}, // 0054 + {0.748047f, 0.582031f, 0.789063f, 0.638672f, 0.0625f, -28.1875f, 20.1250f, 21, 29}, // 0055 + {0.658203f, 0.560547f, 0.703125f, 0.617188f, -1.6875f, -28.1875f, 18.6875f, 23, 29}, // 0056 + {0.923828f, 0.558594f, 0.980469f, 0.615234f, -1.5000f, -28.1875f, 25.8125f, 29, 29}, // 0057 + {0.000000f, 0.566406f, 0.042969f, 0.623047f, -1.2500f, -28.1875f, 18.6875f, 22, 29}, // 0058 + {0.044922f, 0.566406f, 0.087891f, 0.623047f, -1.5625f, -28.1875f, 18.6875f, 22, 29}, // 0059 + {0.078125f, 0.636719f, 0.115234f, 0.693359f, -0.6875f, -28.1875f, 16.6875f, 19, 29}, // 005a + {0.404297f, 0.671875f, 0.423828f, 0.746094f, 0.1250f, -31.8125f, 8.4375f, 10, 38}, // 005b + {0.964844f, 0.292969f, 0.996094f, 0.353516f, -1.6250f, -28.2500f, 12.3750f, 16, 31}, // 005c + {0.941406f, 0.675781f, 0.960938f, 0.750000f, -1.8125f, -31.8125f, 8.3750f, 10, 38}, // 005d + {0.964844f, 0.414063f, 0.994141f, 0.447266f, -1.1250f, -28.2500f, 12.7500f, 15, 17}, // 005e + {0.777344f, 0.699219f, 0.810547f, 0.712891f, -1.8750f, -4.0625f, 13.3125f, 17, 7}, // 005f + {0.705078f, 0.560547f, 0.726563f, 0.578125f, -0.8750f, -29.2500f, 9.8750f, 11, 9}, // 0060 + {0.632813f, 0.677734f, 0.667969f, 0.722656f, -0.7500f, -22.3125f, 16.0625f, 18, 23}, // 0061 + {0.175781f, 0.578125f, 0.210938f, 0.638672f, -0.0625f, -29.8750f, 16.7500f, 18, 31}, // 0062 + {0.832031f, 0.582031f, 0.865234f, 0.626953f, -0.7500f, -22.2500f, 15.4375f, 17, 23}, // 0063 + {0.570313f, 0.623047f, 0.605469f, 0.683594f, -0.6875f, -29.8750f, 16.7500f, 18, 31}, // 0064 + {0.515625f, 0.681641f, 0.550781f, 0.726563f, -0.7500f, -22.2500f, 15.5000f, 18, 23}, // 0065 + {0.486328f, 0.677734f, 0.513672f, 0.738281f, -1.3125f, -30.2500f, 10.0625f, 14, 31}, // 0066 + {0.117188f, 0.636719f, 0.152344f, 0.695313f, -0.6250f, -22.3125f, 16.7500f, 18, 30}, // 0067 + {0.964844f, 0.169922f, 0.998047f, 0.228516f, -0.1250f, -29.9375f, 16.6875f, 17, 30}, // 0068 + {0.982422f, 0.558594f, 0.998047f, 0.617188f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 0069 + {0.191406f, 0.640625f, 0.212891f, 0.714844f, -3.1875f, -29.9375f, 7.8125f, 11, 38}, // 006a + {0.154297f, 0.640625f, 0.189453f, 0.699219f, -0.0625f, -29.9375f, 15.5000f, 18, 30}, // 006b + {0.587891f, 0.685547f, 0.603516f, 0.744141f, 0.1875f, -29.9375f, 7.7500f, 8, 30}, // 006c + {0.765625f, 0.400391f, 0.816406f, 0.445313f, -0.0625f, -22.3125f, 25.6875f, 26, 23}, // 006d + {0.037109f, 0.683594f, 0.070313f, 0.728516f, -0.0625f, -22.3125f, 16.8125f, 17, 23}, // 006e + {0.419922f, 0.363281f, 0.457031f, 0.408203f, -0.7500f, -22.2500f, 16.7500f, 19, 23}, // 006f + {0.677734f, 0.640625f, 0.712891f, 0.699219f, -0.0625f, -22.3125f, 16.7500f, 18, 30}, // 0070 + {0.714844f, 0.640625f, 0.750000f, 0.699219f, -0.6875f, -22.2500f, 16.7500f, 18, 30}, // 0071 + {0.242188f, 0.693359f, 0.267578f, 0.738281f, -0.0625f, -22.3125f, 10.4375f, 13, 23}, // 0072 + {0.552734f, 0.685547f, 0.585938f, 0.730469f, -0.8750f, -22.2500f, 15.0000f, 17, 23}, // 0073 + {0.214844f, 0.693359f, 0.240234f, 0.746094f, -1.5000f, -26.4375f, 10.1875f, 13, 27}, // 0074 + {0.826172f, 0.689453f, 0.859375f, 0.734375f, -0.1250f, -21.9375f, 16.7500f, 17, 23}, // 0075 + {0.302734f, 0.494141f, 0.339844f, 0.537109f, -1.5000f, -22.0000f, 15.0000f, 19, 22}, // 0076 + {0.212891f, 0.494141f, 0.261719f, 0.537109f, -1.3750f, -22.0000f, 22.0625f, 25, 22}, // 0077 + {0.000000f, 0.683594f, 0.035156f, 0.726563f, -1.4375f, -22.0000f, 15.0000f, 18, 22}, // 0078 + {0.728516f, 0.490234f, 0.765625f, 0.548828f, -1.6875f, -22.0000f, 15.0000f, 19, 30}, // 0079 + {0.962891f, 0.691406f, 0.996094f, 0.734375f, -0.6875f, -22.0000f, 15.0000f, 17, 22}, // 007a + {0.466797f, 0.238281f, 0.492188f, 0.310547f, -1.1250f, -30.5625f, 10.0000f, 13, 37}, // 007b + {0.072266f, 0.695313f, 0.085938f, 0.759766f, 0.1875f, -28.1875f, 7.4375f, 7, 33}, // 007c + {0.964844f, 0.617188f, 0.990234f, 0.689453f, -1.5000f, -30.5625f, 10.0000f, 13, 37}, // 007d + {0.087891f, 0.697266f, 0.126953f, 0.718750f, -0.1875f, -17.3750f, 19.6250f, 20, 11}, // 007e + {0.000000f, 0.000000f, 0.001953f, 0.001953f, -2.0000f, -4.0000f, 0.1875f, 1, 1}, // 007f +// RANGE: 0xfffd - 0xfffe, start 0x81 + {0.146484f, 0.375000f, 0.208984f, 0.470703f, -0.6250f, -39.6875f, 30.1875f, 32, 49}, // fffd }; const AtlasCharRange font_UBUNTU24_ranges[] = { { 32, 128, 0 }, - { 128, 129, 96 }, - { 162, 256, 97 }, - { 256, 384, 191 }, - { 1024, 1280, 319 }, - { 8481, 8483, 575 }, - { 65533, 65534, 577 }, + { 65533, 65534, 96 }, }; const AtlasFont font_UBUNTU24 = { - -8.968750f, // padding + -9.125000f, // padding 49.000000f, // height 37.687500f, // ascend 0.750000f, // distslope font_UBUNTU24_chardata, font_UBUNTU24_ranges, - 7, + 2, "UBUNTU24", // name }; const AtlasFont *ui_fonts[1] = { &font_UBUNTU24, }; -const AtlasImage ui_images[24] = { - {0.456299f, 0.810547f, 0.463623f, 0.869141f, 16, 16, "I_SOLIDWHITE"}, - {0.819092f, 0.001953f, 0.833740f, 0.119141f, 31, 31, "I_CROSS"}, - {0.676514f, 0.001953f, 0.691650f, 0.123047f, 32, 32, "I_CIRCLE"}, - {0.707275f, 0.119141f, 0.720947f, 0.228516f, 29, 29, "I_SQUARE"}, - {0.739502f, 0.001953f, 0.755615f, 0.111328f, 34, 29, "I_TRIANGLE"}, - {0.957764f, 0.001953f, 0.990967f, 0.048828f, 69, 13, "I_SELECT"}, - {0.901611f, 0.236328f, 0.929443f, 0.283203f, 58, 13, "I_START"}, - {0.525146f, 0.443359f, 0.531006f, 0.537109f, 13, 25, "I_ARROW"}, - {0.393311f, 0.001953f, 0.421631f, 0.162109f, 59, 42, "I_DIR"}, - {0.366455f, 0.001953f, 0.392334f, 0.205078f, 54, 53, "I_ROUND"}, - {0.142334f, 0.001953f, 0.184326f, 0.330078f, 87, 85, "I_STICK"}, - {0.309814f, 0.001953f, 0.365479f, 0.134766f, 115, 35, "I_SHOULDER"}, - {0.739502f, 0.119141f, 0.753174f, 0.228516f, 29, 29, "I_CHECKEDBOX"}, - {0.422607f, 0.001953f, 0.460693f, 0.115234f, 79, 30, "I_RECT"}, - {0.000244f, 0.001953f, 0.059814f, 0.470703f, 123, 121, "I_STICKBG"}, - {0.185303f, 0.001953f, 0.237549f, 0.244141f, 108, 63, "I_BG"}, - {0.727295f, 0.291016f, 0.731201f, 0.345703f, 9, 15, "I_L"}, - {0.666260f, 0.435547f, 0.672119f, 0.490234f, 13, 15, "I_R"}, - {0.461670f, 0.001953f, 0.484619f, 0.185547f, 48, 48, "I_DROP_SHADOW"}, - {0.800537f, 0.001953f, 0.818115f, 0.099609f, 37, 26, "I_LINES"}, - {0.892334f, 0.001953f, 0.909912f, 0.095703f, 37, 25, "I_GRID"}, - {0.060791f, 0.001953f, 0.141357f, 0.224609f, 166, 58, "I_LOGO"}, - {0.238525f, 0.001953f, 0.273193f, 0.279297f, 72, 72, "I_ICON"}, - {0.274170f, 0.001953f, 0.308838f, 0.279297f, 72, 72, "I_ICONGOLD"}, +const AtlasImage ui_images[33] = { + {0.213867f, 0.323242f, 0.243164f, 0.352539f, 16, 16, "I_SOLIDWHITE"}, + {0.584961f, 0.491211f, 0.655273f, 0.561523f, 37, 37, "I_CROSS"}, + {0.747070f, 0.323242f, 0.821289f, 0.397461f, 39, 39, "I_CIRCLE"}, + {0.659180f, 0.491211f, 0.725586f, 0.557617f, 35, 35, "I_SQUARE"}, + {0.502930f, 0.491211f, 0.581055f, 0.557617f, 41, 35, "I_TRIANGLE"}, + {0.213867f, 0.543945f, 0.374023f, 0.573242f, 83, 16, "I_SELECT"}, + {0.729492f, 0.549805f, 0.862305f, 0.579102f, 69, 16, "I_START"}, + {0.911133f, 0.676758f, 0.938477f, 0.733398f, 15, 30, "I_ARROW"}, + {0.000977f, 0.483398f, 0.114258f, 0.563477f, 59, 42, "I_DIR"}, + {0.887695f, 0.454102f, 0.991211f, 0.555664f, 54, 53, "I_ROUND"}, + {0.346680f, 0.483398f, 0.499023f, 0.540039f, 79, 30, "I_RECT"}, + {0.708008f, 0.000977f, 0.875977f, 0.165039f, 87, 85, "I_STICK"}, + {0.254883f, 0.000977f, 0.493164f, 0.235352f, 123, 121, "I_STICK_BG"}, + {0.346680f, 0.413086f, 0.569336f, 0.479492f, 115, 35, "I_SHOULDER"}, + {0.000977f, 0.375977f, 0.143555f, 0.479492f, 74, 54, "I_DIR_LINE"}, + {0.213867f, 0.364258f, 0.342773f, 0.491211f, 67, 66, "I_ROUND_LINE"}, + {0.573242f, 0.413086f, 0.762695f, 0.487305f, 98, 39, "I_RECT_LINE"}, + {0.467773f, 0.323242f, 0.743164f, 0.409180f, 142, 45, "I_SHOULDER_LINE"}, + {0.497070f, 0.000977f, 0.704102f, 0.204102f, 107, 105, "I_STICK_LINE"}, + {0.000977f, 0.000977f, 0.250977f, 0.247070f, 129, 127, "I_STICK_BG_LINE"}, + {0.377930f, 0.543945f, 0.444336f, 0.610352f, 35, 35, "I_CHECKEDBOX"}, + {0.254883f, 0.239258f, 0.463867f, 0.360352f, 108, 63, "I_BG"}, + {0.000977f, 0.250977f, 0.209961f, 0.372070f, 108, 63, "I_BG_GOLD"}, + {0.424805f, 0.614258f, 0.444336f, 0.647461f, 11, 18, "I_L"}, + {0.776367f, 0.168945f, 0.805664f, 0.202148f, 16, 18, "I_R"}, + {0.118164f, 0.483398f, 0.209961f, 0.575195f, 48, 48, "I_DROP_SHADOW"}, + {0.879883f, 0.106445f, 0.950195f, 0.155273f, 37, 26, "I_LINES"}, + {0.346680f, 0.364258f, 0.416992f, 0.411133f, 37, 25, "I_GRID"}, + {0.497070f, 0.208008f, 0.819336f, 0.319336f, 166, 58, "I_LOGO"}, + {0.823242f, 0.168945f, 0.961914f, 0.307617f, 72, 72, "I_ICON"}, + {0.823242f, 0.311523f, 0.961914f, 0.450195f, 72, 72, "I_ICONGOLD"}, + {0.879883f, 0.000977f, 0.993164f, 0.102539f, 59, 53, "I_FOLDER"}, + {0.766602f, 0.454102f, 0.883789f, 0.545898f, 61, 48, "I_UP_DIRECTORY"}, }; const Atlas ui_atlas = { "ui_atlas.zim", ui_fonts, 1, - ui_images, 24, + ui_images, 33, }; diff --git a/Windows/DebugLog.bat b/Windows/DebugLog.bat new file mode 100644 index 0000000000..8d5aee62d6 --- /dev/null +++ b/Windows/DebugLog.bat @@ -0,0 +1,17 @@ +@echo off +set LOGFILE=ppsspplog.txt + +del "%LOGFILE%" 2> NUL +if exist PPSSPPDebug64.exe ( + PPSSPPDebug64.exe --log="%LOGFILE%" + goto exit +) +if exist PPSSPPDebug.exe ( + PPSSPPDebug.exe --log="%LOGFILE%" + goto exit +) + +echo Unable to find PPSSPPDebug.exe. +pause + +:exit \ No newline at end of file diff --git a/Windows/Debugger/BreakpointWindow.cpp b/Windows/Debugger/BreakpointWindow.cpp index 0cb98099f6..b019318bdb 100644 --- a/Windows/Debugger/BreakpointWindow.cpp +++ b/Windows/Debugger/BreakpointWindow.cpp @@ -148,7 +148,7 @@ bool BreakpointWindow::fetchDialogData(HWND hwnd) if (cpu->parseExpression(exp,size) == false) { - sprintf(errorMessage,"Invalid expression \"%s\".",str); + sprintf(errorMessage,"Invalid expression \"%s\".",exp); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index e314b27c4a..b842893c28 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -31,22 +31,22 @@ extern HMENU g_hPopupMenus; void CtrlDisAsmView::init() { - WNDCLASSEX wc; - - wc.cbSize = sizeof(wc); - wc.lpszClassName = szClassName; - wc.hInstance = GetModuleHandle(0); - wc.lpfnWndProc = CtrlDisAsmView::wndProc; - wc.hCursor = LoadCursor (NULL, IDC_ARROW); - wc.hIcon = 0; - wc.lpszMenuName = 0; - wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); - wc.style = 0; - wc.cbClsExtra = 0; - wc.cbWndExtra = sizeof( CtrlDisAsmView * ); - wc.hIconSm = 0; + WNDCLASSEX wc; - RegisterClassEx(&wc); + wc.cbSize = sizeof(wc); + wc.lpszClassName = szClassName; + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = CtrlDisAsmView::wndProc; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hIcon = 0; + wc.lpszMenuName = 0; + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + wc.style = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof( CtrlDisAsmView * ); + wc.hIconSm = 0; + + RegisterClassEx(&wc); } void CtrlDisAsmView::deinit() @@ -54,185 +54,28 @@ void CtrlDisAsmView::deinit() //UnregisterClass(szClassName, hInst) } -#define NUM_LANES 16 - -bool compareBranchLines(BranchLine& a,BranchLine& b) -{ - return a.first < b.first; -} - void CtrlDisAsmView::scanFunctions() { - struct LaneInfo - { - bool used; - u32 end; - }; - - u32 pos = windowStart; - u32 windowEnd = windowStart+visibleRows*instructionSize; - - visibleFunctionAddresses.clear(); - strayLines.clear(); - - while (pos < windowEnd) - { - SymbolInfo info; - if (symbolMap.GetSymbolInfo(&info,pos)) - { - u32 hash = XXH32(Memory::GetPointer(info.address),info.size,0xBACD7814); - u32 funcEnd = info.address+info.size; - - visibleFunctionAddresses.push_back(info.address); - - auto it = functions.find(info.address); - if (it != functions.end() && it->second.hash == hash) - { - // function is unchaged - pos = funcEnd; - continue; - } - - DisassemblyFunction func; - func.hash = hash; - - LaneInfo lanes[NUM_LANES]; - for (int i = 0; i < NUM_LANES; i++) - lanes[i].used = false; - - - for (u32 funcPos = info.address; funcPos < funcEnd; funcPos += instructionSize) - { - MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(debugger,funcPos); - - bool inFunction = (opInfo.branchTarget >= info.address && opInfo.branchTarget < funcEnd); - if (opInfo.isBranch && !opInfo.isBranchToRegister && !opInfo.isLinkedBranch && inFunction) - { - BranchLine line; - if (opInfo.branchTarget < funcPos) - { - line.first = opInfo.branchTarget; - line.second = funcPos; - line.type = LINE_UP; - } else { - line.first = funcPos; - line.second = opInfo.branchTarget; - line.type = LINE_DOWN; - } - - func.lines.push_back(line); - } - } - - std::sort(func.lines.begin(),func.lines.end(),compareBranchLines); - for (size_t i = 0; i < func.lines.size(); i++) - { - for (int l = 0; l < NUM_LANES; l++) - { - if (func.lines[i].first > lanes[l].end) - lanes[l].used = false; - } - - int lane = -1; - for (int l = 0; l < NUM_LANES; l++) - { - if (lanes[l].used == false) - { - lane = l; - break; - } - } - - if (lane == -1) - { - // error - continue; - } - - lanes[lane].end = func.lines[i].second; - lanes[lane].used = true; - func.lines[i].laneIndex = lane; - } - - functions[info.address] = func; - pos = funcEnd; - } else { - MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(debugger,pos); - if (opInfo.isBranch && !opInfo.isBranchToRegister && !opInfo.isLinkedBranch) - { - BranchLine line; - if (opInfo.branchTarget < pos) - { - line.first = opInfo.branchTarget; - line.second = pos; - line.type = LINE_UP; - } else { - line.first = pos; - line.second = opInfo.branchTarget; - line.type = LINE_DOWN; - } - - strayLines.push_back(line); - } - - pos += instructionSize; - } - } - - // calculate lanes for strayBranches - LaneInfo lanes[NUM_LANES]; - for (int i = 0; i < NUM_LANES; i++) - lanes[i].used = false; - - std::sort(strayLines.begin(),strayLines.end(),compareBranchLines); - for (size_t i = 0; i < strayLines.size(); i++) - { - for (int l = 0; l < NUM_LANES; l++) - { - if (strayLines[i].first > lanes[l].end) - lanes[l].used = false; - } - - int lane = -1; - for (int l = 0; l < NUM_LANES; l++) - { - if (lanes[l].used == false) - { - lane = l; - break; - } - } - - if (lane == -1) - { - // error - continue; - } - - lanes[lane].end = strayLines[i].second; - lanes[lane].used = true; - strayLines[i].laneIndex = lane; - } - + manager.analyze(windowStart,manager.getNthNextAddress(windowStart,visibleRows)-windowStart); } LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CtrlDisAsmView *ccp = CtrlDisAsmView::getFrom(hwnd); static bool lmbDown=false,rmbDown=false; - switch(msg) - { - case WM_NCCREATE: - // Allocate a new CustCtrl structure for this window. - ccp = new CtrlDisAsmView(hwnd); + switch(msg) + { + case WM_NCCREATE: + // Allocate a new CustCtrl structure for this window. + ccp = new CtrlDisAsmView(hwnd); - // Continue with window creation. - return ccp != NULL; + // Continue with window creation. + return ccp != NULL; // Clean up when the window is destroyed. - case WM_NCDESTROY: - delete ccp; - break; + case WM_NCDESTROY: + delete ccp; + break; case WM_SETFONT: break; case WM_SIZE: @@ -293,17 +136,17 @@ LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA } } return DLGC_WANTCHARS|DLGC_WANTARROWS; - default: - break; - } + default: + break; + } - return DefWindowProc(hwnd, msg, wParam, lParam); + return DefWindowProc(hwnd, msg, wParam, lParam); } CtrlDisAsmView *CtrlDisAsmView::getFrom(HWND hwnd) { - return (CtrlDisAsmView *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + return (CtrlDisAsmView *)GetWindowLongPtr(hwnd, GWLP_USERDATA); } @@ -324,7 +167,6 @@ CtrlDisAsmView::CtrlDisAsmView(HWND _wnd) boldfont = CreateFont(rowHeight-2,charWidth,0,0,FW_DEMIBOLD,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH, L"Lucida Console"); curAddress=0; - instructionSize=4; showHex=false; hasFocus = false; dontRedraw = false; @@ -359,11 +201,11 @@ COLORREF scaleColor(COLORREF color, float factor) return (color & 0xFF000000) | (b << 16) | (g << 8) | r; } -bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels) +bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData) { if (displaySymbols) { - const char* addressSymbol = debugger->findSymbolForAddress(address); + const char* addressSymbol = symbolMap.GetLabelName(address); if (addressSymbol != NULL) { for (int k = 0; addressSymbol[k] != 0; k++) @@ -384,72 +226,30 @@ bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbrevia return false; } } else { - sprintf(dest,"%08X %08X",address,Memory::Read_U32(address)); + if (showData) + sprintf(dest,"%08X %08X",address,Memory::Read_U32(address)); + else + sprintf(dest,"%08X",address); return false; } } -void CtrlDisAsmView::parseDisasm(const char* disasm, char* opcode, char* arguments) +std::string trimString(std::string input) { - branchTarget = -1; - branchRegister = -1; - - // copy opcode - while (*disasm != 0 && *disasm != '\t') + size_t pos = input.find_first_not_of(" \t"); + if (pos != 0 && pos != std::string::npos) { - *opcode++ = *disasm++; - } - *opcode = 0; - - if (*disasm++ == 0) - { - *arguments = 0; - return; + input = input.erase(0,pos); } - const char* jumpAddress = strstr(disasm,"->$"); - const char* jumpRegister = strstr(disasm,"->"); - while (*disasm != 0) + pos = input.find_last_not_of(" \t"); + if (pos != std::string::npos) { - // parse symbol - if (disasm == jumpAddress) - { - sscanf(disasm+3,"%08x",&branchTarget); - - const char* addressSymbol = debugger->findSymbolForAddress(branchTarget); - if (addressSymbol != NULL && displaySymbols) - { - arguments += sprintf(arguments,"%s",addressSymbol); - } else { - arguments += sprintf(arguments,"0x%08X",branchTarget); - } - - disasm += 3+8; - continue; - } - - if (disasm == jumpRegister) - { - disasm += 2; - for (int i = 0; i < 32; i++) - { - if (strcasecmp(jumpRegister+2,debugger->GetRegName(0,i)) == 0) - { - branchRegister = i; - break; - } - } - } - - if (*disasm == ' ') - { - disasm++; - continue; - } - *arguments++ = *disasm++; + size_t size = input.length()-pos-1; + input = input.erase(pos+1,size); } - *arguments = 0; + return input; } void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) @@ -465,6 +265,33 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) if (!result) return; + // check if it changes registers first + auto seperator = op.find('='); + if (seperator != std::string::npos) + { + std::string registerName = trimString(op.substr(0,seperator)); + std::string expression = trimString(op.substr(seperator+1)); + + u32 value; + if (parseExpression(expression.c_str(),debugger,value) == true) + { + for (int cat = 0; cat < debugger->GetNumCategories(); cat++) + { + for (int reg = 0; reg < debugger->GetNumRegsInCategory(cat); reg++) + { + if (strcasecmp(debugger->GetRegName(cat,reg),registerName.c_str()) == 0) + { + debugger->SetRegValue(cat,reg,value); + SendMessage(GetParent(wnd),WM_DEB_UPDATE,0,0); + return; + } + } + } + } + + // try to assemble the input if it failed + } + result = MIPSAsm::MipsAssembleOpcode(op.c_str(),debugger,address,encoded); if (result == true) { @@ -475,7 +302,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) scanFunctions(); if (address == curAddress) - gotoAddr(curAddress+4); + gotoAddr(manager.getNthNextAddress(curAddress,1)); redraw(); } else { @@ -485,10 +312,10 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) } -void CtrlDisAsmView::drawBranchLine(HDC hdc, BranchLine& line) +void CtrlDisAsmView::drawBranchLine(HDC hdc, std::map& addressPositions, BranchLine& line) { HPEN pen; - u32 windowEnd = windowStart+visibleRows*instructionSize; + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); int topY; int bottomY; @@ -499,8 +326,7 @@ void CtrlDisAsmView::drawBranchLine(HDC hdc, BranchLine& line) { topY = rect.bottom+1; } else { - int row = (line.first-windowStart)/instructionSize; - topY = row*rowHeight + rowHeight/2; + topY = addressPositions[line.first] + rowHeight/2; } if (line.second < windowStart) @@ -510,8 +336,7 @@ void CtrlDisAsmView::drawBranchLine(HDC hdc, BranchLine& line) { bottomY = rect.bottom+1; } else { - int row = (line.second-windowStart)/instructionSize; - bottomY = row*rowHeight + rowHeight/2; + bottomY = addressPositions[line.second] + rowHeight/2; } if ((topY < 0 && bottomY < 0) || (topY > rect.bottom && bottomY > rect.bottom)) @@ -603,19 +428,24 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) HICON breakPoint = (HICON)LoadIcon(GetModuleHandle(0),(LPCWSTR)IDI_STOP); HICON breakPointDisable = (HICON)LoadIcon(GetModuleHandle(0),(LPCWSTR)IDI_STOPDISABLE); + unsigned int address = windowStart; + std::map addressPositions; + + DisassemblyLineInfo line; for (int i = 0; i < visibleRows; i++) { - unsigned int address=windowStart + i*instructionSize; - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,address); + manager.getLine(address,displaySymbols,line); int rowY1 = rowHeight*i; int rowY2 = rowHeight*(i+1); + addressPositions[address] = rowY1; + // draw background COLORREF backgroundColor = whiteBackground ? 0xFFFFFF : debugger->getColor(address); COLORREF textColor = 0x000000; - if (address == debugger->getPC()) + if (isInInterval(address,line.totalSize,debugger->getPC())) { backgroundColor = scaleColor(backgroundColor,1.05f); } @@ -655,48 +485,34 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) SetTextColor(hdc,textColor); char addressText[64]; - getDisasmAddressText(address,addressText,true); + getDisasmAddressText(address,addressText,true,line.type == DISTYPE_OPCODE); TextOutA(hdc,pixelPositions.addressStart,rowY1+2,addressText,(int)strlen(addressText)); - - if (address == debugger->getPC()) + + if (isInInterval(address,line.totalSize,debugger->getPC())) { TextOut(hdc,pixelPositions.opcodeStart-8,rowY1,L"■",1); } - // display opcode - char opcode[64],arguments[256]; - const char *dizz = debugger->disasm(address, instructionSize); - parseDisasm(dizz,opcode,arguments); - // display whether the condition of a branch is met - if (info.isConditional && address == debugger->getPC()) + if (line.info.isConditional && address == debugger->getPC()) { - strcat(arguments,info.conditionMet ? " ; true" : " ; false"); + line.params += line.info.conditionMet ? " ; true" : " ; false"; } - int length = (int) strlen(arguments); - if (length != 0) TextOutA(hdc,pixelPositions.argumentsStart,rowY1+2,arguments,length); + if (line.params.size() != 0) + TextOutA(hdc,pixelPositions.argumentsStart,rowY1+2,line.params.c_str(),(int)line.params.size()); SelectObject(hdc,boldfont); - TextOutA(hdc,pixelPositions.opcodeStart,rowY1+2,opcode,(int)strlen(opcode)); + TextOutA(hdc,pixelPositions.opcodeStart,rowY1+2,line.name.c_str(),(int)line.name.size()); SelectObject(hdc,font); + + address += line.totalSize; } - for (size_t i = 0; i < visibleFunctionAddresses.size(); i++) + std::vector branchLines = manager.getBranchLines(windowStart,address-windowStart); + for (size_t i = 0; i < branchLines.size(); i++) { - auto it = functions.find(visibleFunctionAddresses[i]); - if (it == functions.end()) continue; - DisassemblyFunction& func = it->second; - - for (size_t l = 0; l < func.lines.size(); l++) - { - drawBranchLine(hdc,func.lines[l]); - } - } - - for (size_t i = 0; i < strayLines.size(); i++) - { - drawBranchLine(hdc,strayLines[i]); + drawBranchLine(hdc,addressPositions,branchLines[i]); } SelectObject(hdc,oldFont); @@ -726,35 +542,46 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam) switch (wParam & 0xFFFF) { case SB_LINEDOWN: - windowStart += instructionSize; + windowStart = manager.getNthNextAddress(windowStart,1); break; case SB_LINEUP: - windowStart -= instructionSize; + windowStart = manager.getNthPreviousAddress(windowStart,1); break; case SB_PAGEDOWN: - windowStart += visibleRows*instructionSize; + windowStart = manager.getNthNextAddress(windowStart,visibleRows); break; case SB_PAGEUP: - windowStart -= visibleRows*instructionSize; + windowStart = manager.getNthPreviousAddress(windowStart,visibleRows); break; default: return; } + + scanFunctions(); redraw(); } void CtrlDisAsmView::followBranch() { - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,curAddress); + DisassemblyLineInfo line; + manager.getLine(curAddress,true,line); - if (info.isBranch) + if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { - jumpStack.push_back(curAddress); - gotoAddr(info.branchTarget); - } else if (info.hasRelevantAddress) + if (line.info.isBranch) + { + jumpStack.push_back(curAddress); + gotoAddr(line.info.branchTarget); + } else if (line.info.hasRelevantAddress) + { + // well, not exactly a branch, but we can do something anyway + SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,line.info.releventAddress,0); + SetFocus(wnd); + } + } else if (line.type == DISTYPE_DATA) { - // well, not exactly a branch, but we can do something anyway - SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,info.releventAddress,0); + // jump to the start of the current line + SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,curAddress,0); SetFocus(wnd); } } @@ -803,7 +630,7 @@ void CtrlDisAsmView::editBreakpoint() void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) { dontRedraw = false; - u32 windowEnd = windowStart+visibleRows*instructionSize; + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); keyTaken = true; if (KeyDownAsync(VK_CONTROL)) @@ -837,24 +664,38 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) case 'd': // toogle breakpoint enabled toggleBreakpoint(true); break; + case VK_UP: + scrollWindow(-1); + scanFunctions(); + break; + case VK_DOWN: + scrollWindow(1); + scanFunctions(); + break; + case VK_NEXT: + setCurAddress(manager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT)); + break; + case VK_PRIOR: + setCurAddress(windowStart,KeyDownAsync(VK_SHIFT)); + break; } } else { switch (wParam & 0xFFFF) { case VK_DOWN: - setCurAddress(curAddress + instructionSize, KeyDownAsync(VK_SHIFT)); + setCurAddress(manager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); break; case VK_UP: - setCurAddress(curAddress - instructionSize, KeyDownAsync(VK_SHIFT)); + setCurAddress(manager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); break; case VK_NEXT: - if (curAddress != windowEnd - instructionSize && curAddressIsVisible()) { - setCurAddress(windowEnd - instructionSize, KeyDownAsync(VK_SHIFT)); + if (manager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) { + setCurAddress(manager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(curAddress + visibleRows * instructionSize, KeyDownAsync(VK_SHIFT)); + setCurAddress(manager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -863,7 +704,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) setCurAddress(windowStart, KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } else { - setCurAddress(curAddress - visibleRows * instructionSize, KeyDownAsync(VK_SHIFT)); + setCurAddress(manager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT)); scrollAddressIntoView(); } break; @@ -904,19 +745,19 @@ void CtrlDisAsmView::onKeyUp(WPARAM wParam, LPARAM lParam) void CtrlDisAsmView::scrollAddressIntoView() { - u32 windowEnd = windowStart + visibleRows * instructionSize; + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); if (curAddress < windowStart) windowStart = curAddress; else if (curAddress >= windowEnd) - windowStart = curAddress - visibleRows * instructionSize + instructionSize; + windowStart = manager.getNthPreviousAddress(curAddress,visibleRows-1); scanFunctions(); } bool CtrlDisAsmView::curAddressIsVisible() { - u32 windowEnd = windowStart + visibleRows * instructionSize; + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); return curAddress >= windowStart && curAddress < windowEnd; } @@ -988,31 +829,29 @@ void CtrlDisAsmView::onMouseDown(WPARAM wParam, LPARAM lParam, int button) void CtrlDisAsmView::copyInstructions(u32 startAddr, u32 endAddr, bool withDisasm) { - int count = (endAddr - startAddr) / instructionSize; - - char opcode[64], arguments[256]; - int space = count * (withDisasm ? 256 : 32); - char *temp = new char[space]; - - char *p = temp, *end = temp + space; - for (u32 pos = startAddr; pos < endAddr; pos += instructionSize) + if (withDisasm == false) { - if (withDisasm) + int instructionSize = debugger->getInstructionSize(0); + int count = (endAddr - startAddr) / instructionSize; + int space = count * 32; + char *temp = new char[space]; + + char *p = temp, *end = temp + space; + for (u32 pos = startAddr; pos < endAddr; pos += instructionSize) { - const char *dizz = debugger->disasm(pos, instructionSize); - parseDisasm(dizz, opcode, arguments); - p += snprintf(p, end - p, "%s\t%s", opcode, arguments); - } - else p += snprintf(p, end - p, "%08X", debugger->readMemory(pos)); - // Don't leave a trailing newline. - if (pos + instructionSize < endAddr) - p += snprintf(p, end - p, "\r\n"); + // Don't leave a trailing newline. + if (pos + instructionSize < endAddr) + p += snprintf(p, end - p, "\r\n"); + } + W32Util::CopyTextToClipboard(wnd, temp); + delete [] temp; + } else + { + std::string disassembly = disassembleRange(startAddr,endAddr-startAddr); + W32Util::CopyTextToClipboard(wnd, disassembly.c_str()); } - - W32Util::CopyTextToClipboard(wnd, temp); - delete [] temp; } void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) @@ -1071,17 +910,17 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) break; case ID_DISASM_RENAMEFUNCTION: { - int sym = symbolMap.GetSymbolNum(curAddress); - if (sym != -1) + u32 funcBegin = symbolMap.GetFunctionStart(curAddress); + if (funcBegin != -1) { char name[256]; std::string newname; - strncpy_s(name, symbolMap.GetSymbolName(sym),_TRUNCATE); + strncpy_s(name, symbolMap.GetLabelName(funcBegin),_TRUNCATE); if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), L"New function name", name, newname)) { - symbolMap.SetSymbolName(sym, newname.c_str()); - redraw(); + symbolMap.SetLabelName(newname.c_str(),funcBegin); SendMessage(GetParent(wnd),WM_DEB_MAPLOADED,0,0); + redraw(); } } else @@ -1093,17 +932,20 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) case ID_DISASM_REMOVEFUNCTION: { char statusBarTextBuff[256]; - int sym = symbolMap.GetSymbolNum(curAddress); - if (sym != -1) + u32 funcBegin = symbolMap.GetFunctionStart(curAddress); + if (funcBegin != -1) { - u32 funcBegin = symbolMap.GetAddress(sym); - int prev = symbolMap.GetSymbolNum(funcBegin - 1); - if (prev != -1) + u32 prevBegin = symbolMap.GetFunctionStart(funcBegin-1); + if (prevBegin != -1) { - int expandedSize = symbolMap.GetSymbolSize(prev) + symbolMap.GetSymbolSize(sym); - symbolMap.SetSymbolSize(prev, expandedSize); + u32 expandedSize = symbolMap.GetFunctionSize(prevBegin)+symbolMap.GetFunctionSize(funcBegin); + symbolMap.SetFunctionSize(prevBegin,expandedSize); } - symbolMap.RemoveSymbolNum(sym); + + symbolMap.RemoveFunction(funcBegin,true); + symbolMap.SortSymbols(); + manager.clear(); + SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); } else @@ -1117,10 +959,10 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) case ID_DISASM_ADDFUNCTION: { char statusBarTextBuff[256]; - int sym = symbolMap.GetSymbolNum(curAddress); - if (sym != -1) + u32 prevBegin = symbolMap.GetFunctionStart(curAddress); + if (prevBegin != -1) { - if (symbolMap.GetAddress(sym) == curAddress) + if (prevBegin == curAddress) { snprintf(statusBarTextBuff,256, "WARNING: There's already a function entry point at this adress"); SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM) statusBarTextBuff); @@ -1128,21 +970,28 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) else { char symname[128]; - int prevSize = symbolMap.GetSymbolSize(sym); - u32 prevAddr = symbolMap.GetSymbolAddr(sym); - int newSize = curAddress - prevAddr; - symbolMap.SetSymbolSize(sym, newSize); - newSize = prevSize - newSize; + u32 prevSize = symbolMap.GetFunctionSize(prevBegin); + u32 newSize = curAddress-prevBegin; + symbolMap.SetFunctionSize(prevBegin,newSize); + + newSize = prevSize-newSize; snprintf(symname,128,"u_un_%08X",curAddress); - symbolMap.AddSymbol(symname, curAddress, newSize, ST_FUNCTION); + symbolMap.AddFunction(symname,curAddress,newSize); symbolMap.SortSymbols(); + manager.clear(); + SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); } } else { - snprintf(statusBarTextBuff, 256, "WARNING: unable to add function symbol here"); - SendMessage(GetParent(wnd), WM_DEB_SETSTATUSBARTEXT, 0, (LPARAM) statusBarTextBuff); + char symname[128]; + int newSize = selectRangeEnd - selectRangeStart; + snprintf(symname, 128, "u_un_%08X", selectRangeStart); + symbolMap.AddFunction(symname, selectRangeStart, newSize); + symbolMap.SortSymbols(); + + SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); } redraw(); } @@ -1172,51 +1021,76 @@ void CtrlDisAsmView::onMouseMove(WPARAM wParam, LPARAM lParam, int button) void CtrlDisAsmView::updateStatusBarText() { char text[512]; - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,curAddress); + DisassemblyLineInfo line; + manager.getLine(curAddress,true,line); text[0] = 0; - if (info.isDataAccess) + if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { - if (!Memory::IsValidAddress(info.dataAddress)) + if (line.info.isDataAccess) { - sprintf(text,"Invalid address %08X",info.dataAddress); - } else { - switch (info.dataSize) + if (!Memory::IsValidAddress(line.info.dataAddress)) { - case 1: - sprintf(text,"[%08X] = %02X",info.dataAddress,Memory::Read_U8(info.dataAddress)); - break; - case 2: - sprintf(text,"[%08X] = %04X",info.dataAddress,Memory::Read_U16(info.dataAddress)); - break; - case 4: - // TODO: Could also be a float... + sprintf(text,"Invalid address %08X",line.info.dataAddress); + } else { + switch (line.info.dataSize) { - u32 data = Memory::Read_U32(info.dataAddress); - const char* addressSymbol = debugger->findSymbolForAddress(data); - if (addressSymbol) + case 1: + sprintf(text,"[%08X] = %02X",line.info.dataAddress,Memory::Read_U8(line.info.dataAddress)); + break; + case 2: + sprintf(text,"[%08X] = %04X",line.info.dataAddress,Memory::Read_U16(line.info.dataAddress)); + break; + case 4: + // TODO: Could also be a float... { - sprintf(text,"[%08X] = %s (%08X)",info.dataAddress,addressSymbol,data); - } else { - sprintf(text,"[%08X] = %08X",info.dataAddress,data); + u32 data = Memory::Read_U32(line.info.dataAddress); + const char* addressSymbol = symbolMap.GetLabelName(data); + if (addressSymbol) + { + sprintf(text,"[%08X] = %s (%08X)",line.info.dataAddress,addressSymbol,data); + } else { + sprintf(text,"[%08X] = %08X",line.info.dataAddress,data); + } + break; } + case 16: + // TODO: vector break; } - case 16: - // TODO: vector - break; } } - } - if (info.isBranch) - { - const char* addressSymbol = debugger->findSymbolForAddress(info.branchTarget); - if (addressSymbol == NULL) + if (line.info.isBranch) { - sprintf(text,"%08X",info.branchTarget); + const char* addressSymbol = symbolMap.GetLabelName(line.info.branchTarget); + if (addressSymbol == NULL) + { + sprintf(text,"%08X",line.info.branchTarget); + } else { + sprintf(text,"%08X = %s",line.info.branchTarget,addressSymbol); + } + } + } else if (line.type == DISTYPE_DATA) + { + u32 start = symbolMap.GetDataStart(curAddress); + if (start == -1) + start = curAddress; + + u32 diff = curAddress-start; + const char* label = symbolMap.GetLabelName(start); + + if (label != NULL) + { + if (diff != 0) + sprintf(text,"%08X (%s) + %08X",start,label,diff); + else + sprintf(text,"%08X (%s)",start,label); } else { - sprintf(text,"%08X = %s",info.branchTarget,addressSymbol); + if (diff != 0) + sprintf(text,"%08X + %08X",start,diff); + else + sprintf(text,"%08X",start); } } @@ -1226,7 +1100,7 @@ void CtrlDisAsmView::updateStatusBarText() u32 CtrlDisAsmView::yToAddress(int y) { int line = y/rowHeight; - return windowStart + line*instructionSize; + return manager.getNthNextAddress(windowStart,line); } void CtrlDisAsmView::calculatePixelPositions() @@ -1255,9 +1129,9 @@ void CtrlDisAsmView::search(bool continueSearch) searchQuery[i] = tolower(searchQuery[i]); } SetFocus(wnd); - searchAddress = curAddress+instructionSize; + searchAddress = manager.getNthNextAddress(curAddress,1); } else { - searchAddress = matchAddress+instructionSize; + searchAddress = manager.getNthNextAddress(matchAddress,1); } // limit address to sensible ranges @@ -1270,12 +1144,17 @@ void CtrlDisAsmView::search(bool continueSearch) searching = true; redraw(); // so the cursor is disabled + + DisassemblyLineInfo lineInfo; while (searchAddress < 0x0A000000) { - char addressText[64],opcode[64],arguments[256]; - const char *dis = debugger->disasm(searchAddress, instructionSize); - parseDisasm(dis,opcode,arguments); - getDisasmAddressText(searchAddress,addressText,true); + manager.getLine(searchAddress,displaySymbols,lineInfo); + + char addressText[64]; + getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE); + + const char* opcode = lineInfo.name.c_str(); + const char* arguments = lineInfo.params.c_str(); char merged[512]; int mergePos = 0; @@ -1304,7 +1183,7 @@ void CtrlDisAsmView::search(bool continueSearch) return; } - searchAddress += instructionSize; + searchAddress = manager.getNthNextAddress(searchAddress,1); if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000; } @@ -1312,6 +1191,64 @@ void CtrlDisAsmView::search(bool continueSearch) searching = false; } +std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size) +{ + std::string result; + + // gather all branch targets without labels + std::set branchAddresses; + for (u32 i = 0; i < size; i += debugger->getInstructionSize(0)) + { + MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,start+i); + + if (info.isBranch && symbolMap.GetLabelName(info.branchTarget) == NULL) + { + if (branchAddresses.find(info.branchTarget) == branchAddresses.end()) + { + branchAddresses.insert(info.branchTarget); + } + } + } + + u32 disAddress = start; + bool previousLabel = true; + DisassemblyLineInfo line; + while (disAddress < start+size) + { + char addressText[64],buffer[512]; + + manager.getLine(disAddress,displaySymbols,line); + bool isLabel = getDisasmAddressText(disAddress,addressText,false,line.type == DISTYPE_OPCODE); + + if (isLabel) + { + if (!previousLabel) result += "\r\n"; + sprintf(buffer,"%s\r\n\r\n",addressText); + result += buffer; + } else if (branchAddresses.find(disAddress) != branchAddresses.end()) + { + if (!previousLabel) result += "\r\n"; + sprintf(buffer,"pos_%08X:\r\n\r\n",disAddress); + result += buffer; + } + + if (line.info.isBranch && !line.info.isBranchToRegister + && symbolMap.GetLabelName(line.info.branchTarget) == NULL + && branchAddresses.find(line.info.branchTarget) != branchAddresses.end()) + { + sprintf(buffer,"pos_%08X",line.info.branchTarget); + line.params = line.params.substr(0,line.params.find("0x")) + buffer; + } + + sprintf(buffer,"\t%s\t%s\r\n",line.name.c_str(),line.params.c_str()); + result += buffer; + previousLabel = isLabel; + disAddress += line.totalSize; + } + + return result; +} + void CtrlDisAsmView::disassembleToFile() { wchar_t fileName[MAX_PATH]; @@ -1342,58 +1279,14 @@ void CtrlDisAsmView::disassembleToFile() if (GetSaveFileName(&ofn) == false) return; - FILE* output = _wfopen(fileName, L"w"); + FILE* output = _wfopen(fileName, L"wb"); if (output == NULL) { MessageBox(wnd,L"Could not open file!",L"Error",MB_OK); return; } - // gather all branch targets without labels - std::set branchAddresses; - for (u32 i = 0; i < size; i += instructionSize) - { - char opcode[64],arguments[256]; - const char *dis = debugger->disasm(curAddress+i, instructionSize); - parseDisasm(dis,opcode,arguments); - - if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL) - { - if (branchAddresses.find(branchTarget) == branchAddresses.end()) - { - branchAddresses.insert(branchTarget); - } - } - } - - bool previousLabel = true; - for (u32 i = 0; i < size; i += instructionSize) - { - u32 disAddress = curAddress+i; - - char addressText[64],opcode[64],arguments[256]; - const char *dis = debugger->disasm(disAddress, instructionSize); - parseDisasm(dis,opcode,arguments); - bool isLabel = getDisasmAddressText(disAddress,addressText,false); - - if (isLabel) - { - if (!previousLabel) fprintf(output,"\n"); - fprintf(output,"%s\n\n",addressText); - } else if (branchAddresses.find(disAddress) != branchAddresses.end()) - { - if (!previousLabel) fprintf(output,"\n"); - fprintf(output,"pos_%08X:\n\n",disAddress); - } - - if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL) - { - char* str = strstr(arguments,"0x"); - sprintf(str,"pos_%08X",branchTarget); - } - - fprintf(output,"\t%s\t%s\n",opcode,arguments); - previousLabel = isLabel; - } + std::string disassembly = disassembleRange(curAddress,size); + fprintf(output,"%s",disassembly.c_str()); fclose(output); MessageBox(wnd,L"Finished!",L"Done",MB_OK); @@ -1401,9 +1294,26 @@ void CtrlDisAsmView::disassembleToFile() void CtrlDisAsmView::getOpcodeText(u32 address, char* dest) { - char opcode[64]; - char arguments[256]; - const char *dis = debugger->disasm(address, instructionSize); - parseDisasm(dis,opcode,arguments); - sprintf(dest,"%s %s",opcode,arguments); + DisassemblyLineInfo line; + address = manager.getStartAddress(address); + manager.getLine(address,displaySymbols,line); + sprintf(dest,"%s %s",line.name.c_str(),line.params.c_str()); +} + +void CtrlDisAsmView::scrollStepping(u32 newPc) +{ + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + + newPc = manager.getStartAddress(newPc); + if (newPc >= windowEnd || newPc >= manager.getNthPreviousAddress(windowEnd,1)) + { + windowStart = manager.getNthPreviousAddress(newPc,visibleRows-2); + } +} + +u32 CtrlDisAsmView::getInstructionSizeAt(u32 address) +{ + u32 start = manager.getStartAddress(address); + u32 next = manager.getNthNextAddress(start,1); + return next-address; } \ No newline at end of file diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index 67278596b8..36936d3def 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -19,6 +19,8 @@ // CtrlDisAsmView::getFrom(GetDlgItem(yourdialog, IDC_yourid)). #include "../../Core/Debugger/DebugInterface.h" +#include "../../Core/Debugger/DisassemblyManager.h" + #include "Common/CommonWindows.h" #include @@ -27,23 +29,6 @@ using std::min; using std::max; - -enum LineType { LINE_UP, LINE_DOWN, LINE_RIGHT }; - -struct BranchLine -{ - u32 first; - u32 second; - LineType type; - int laneIndex; -}; - -struct DisassemblyFunction -{ - u32 hash; - std::vector lines; -}; - class CtrlDisAsmView { HWND wnd; @@ -51,10 +36,7 @@ class CtrlDisAsmView HFONT boldfont; RECT rect; - std::map functions; - std::vector visibleFunctionAddresses; - std::vector strayLines; - + DisassemblyManager manager; u32 curAddress; u32 selectRangeStart; u32 selectRangeEnd; @@ -68,11 +50,8 @@ class CtrlDisAsmView u32 windowStart; int visibleRows; - int instructionSize; bool whiteBackground; bool displaySymbols; - u32 branchTarget; - int branchRegister; struct { int addressStart; @@ -90,14 +69,14 @@ class CtrlDisAsmView bool keyTaken; void assembleOpcode(u32 address, std::string defaultText); + std::string disassembleRange(u32 start, u32 size); void disassembleToFile(); void search(bool continueSearch); void followBranch(); void calculatePixelPositions(); - bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels); - void parseDisasm(const char* disasm, char* opcode, char* arguments); + bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData); void updateStatusBarText(); - void drawBranchLine(HDC hdc, BranchLine& line); + void drawBranchLine(HDC hdc, std::map& addressPositions, BranchLine& line); void copyInstructions(u32 startAddr, u32 endAddr, bool withDisasm); public: CtrlDisAsmView(HWND _wnd); @@ -119,12 +98,7 @@ public: bool curAddressIsVisible(); void redraw(); void scanFunctions(); - void clearFunctions() - { - functions.clear(); - visibleFunctionAddresses.clear(); - strayLines.clear(); - }; + void clearFunctions() { manager.clear(); }; void getOpcodeText(u32 address, char* dest); int getRowHeight() { return rowHeight; }; @@ -135,22 +109,24 @@ public: { debugger=deb; curAddress=debugger->getPC(); - instructionSize=debugger->getInstructionSize(0); + manager.setCpu(deb); } DebugInterface *getDebugger() { return debugger; } - u32 getWindowEnd() { return windowStart+visibleRows*instructionSize; }; + void scrollStepping(u32 newPc); + u32 getInstructionSizeAt(u32 address); + void gotoAddr(unsigned int addr) { - u32 windowEnd = windowStart+visibleRows*instructionSize; - u32 newAddress = addr&(~(instructionSize-1)); + u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); + u32 newAddress = manager.getStartAddress(addr); if (newAddress < windowStart || newAddress >= windowEnd) { - windowStart = newAddress-visibleRows/2*instructionSize; + windowStart = manager.getNthPreviousAddress(newAddress,visibleRows/2); } setCurAddress(newAddress); @@ -159,7 +135,7 @@ public: } void gotoPC() { - gotoAddr(debugger->getPC()&(~(instructionSize-1))); + gotoAddr(debugger->getPC()); } u32 getSelection() { @@ -176,14 +152,19 @@ public: void scrollWindow(int lines) { - windowStart += lines*instructionSize; + if (lines < 0) + windowStart = manager.getNthPreviousAddress(windowStart,abs(lines)); + else + windowStart = manager.getNthNextAddress(windowStart,lines); + scanFunctions(); redraw(); } void setCurAddress(u32 newAddress, bool extend = false) { - u32 after = newAddress + instructionSize; + newAddress = manager.getStartAddress(newAddress); + u32 after = manager.getNthNextAddress(newAddress,1); curAddress = newAddress; selectRangeStart = extend ? std::min(selectRangeStart, newAddress) : newAddress; selectRangeEnd = extend ? std::max(selectRangeEnd, after) : after; diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 8bf2c4c3ba..2245bba009 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -434,19 +434,12 @@ void CtrlMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) switch (TrackPopupMenuEx(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,wnd,0)) { case ID_MEMVIEW_DUMP: - - if (!Core_IsStepping()) // If emulator isn't paused { - MessageBox(wnd,L"You have to pause the emulator first",0,0); - break; - } - else - { - DumpMemoryWindow dump(wnd,debugger); + DumpMemoryWindow dump(wnd, debugger); dump.exec(); break; } - + case ID_MEMVIEW_COPYVALUE_8: { char temp[24]; @@ -702,4 +695,4 @@ void CtrlMemView::search(bool continueSearch) MessageBox(wnd,L"Not found",L"Search",MB_OK); searching = false; redraw(); -} \ No newline at end of file +} diff --git a/Windows/Debugger/CtrlRegisterList.cpp b/Windows/Debugger/CtrlRegisterList.cpp index f8fc9390c3..02d006788d 100644 --- a/Windows/Debugger/CtrlRegisterList.cpp +++ b/Windows/Debugger/CtrlRegisterList.cpp @@ -300,24 +300,6 @@ void CtrlRegisterList::onPaint(WPARAM wParam, LPARAM lParam) SetTextColor(hdc,0x004000); TextOutA(hdc,77,rowY1,temp,(int)strlen(temp)); } - - /* - } - SetTextColor(hdc,0x007000); - - TextOut(hdc,70,rowY1,dis,strlen(dis)); - if (desc[0]==0) - strcpy(desc,debugger->getDescription(address)); - SetTextColor(hdc,0x0000FF); - //char temp[256]; - //UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE); - if (strlen(desc)) - TextOut(hdc,280,rowY1,desc,strlen(desc)); - if (debugger->isBreakpoint(address)) - { - DrawIconEx(hdc,2,rowY1,breakPoint,32,32,0,0,DI_NORMAL); - } - }*/ } SelectObject(hdc,oldFont); @@ -454,7 +436,7 @@ void CtrlRegisterList::editRegisterValue() } char temp[256]; - sprintf(temp,"%08X",val); + sprintf(temp,"0x%08X",val); std::string value = temp; if (InputBox_GetString(GetModuleHandle(NULL),wnd,L"Set new value",value,value)) { @@ -521,16 +503,40 @@ void CtrlRegisterList::onMouseDown(WPARAM wParam, LPARAM lParam, int button) void CtrlRegisterList::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { - if (button==2) + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + if (button==2 && x>16) { //popup menu? int cat = category; int reg = selection; - if (selection >= cpu->GetNumRegsInCategory(cat)) + u32 val; + if (selection < cpu->GetNumRegsInCategory(cat)) + { + val = cpu->GetRegValue(cat, reg); + } + else if (cat == 0 && selection < REGISTERS_END) + { + switch (selection) + { + case REGISTER_PC: + val = cpu->GetPC(); + break; + case REGISTER_HI: + val = cpu->GetHi(); + break; + case REGISTER_LO: + val = cpu->GetLo(); + break; + } + } + else + { return; + } POINT pt; GetCursorPos(&pt); - u32 val = cpu->GetRegValue(cat,reg); switch(TrackPopupMenuEx(GetSubMenu(g_hPopupMenus,3),TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,wnd,0)) { case ID_REGLIST_GOTOINMEMORYVIEW: @@ -550,8 +556,6 @@ void CtrlRegisterList::onMouseUp(WPARAM wParam, LPARAM lParam, int button) } return; } - int x = LOWORD(lParam); - int y = HIWORD(lParam); if (x>16) { selection=yToIndex(y); diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 4e33ca76e4..7e5c30947b 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -101,8 +101,6 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di CtrlRegisterList *rl = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST)); rl->setCPU(cpu); - - symbolMap.FillSymbolComboBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); leftTabs = new TabControl(GetDlgItem(m_hDlg,IDC_LEFTTABS)); leftTabs->SetIgnoreBottomMargin(true); @@ -164,19 +162,15 @@ void CDisasm::stepInto() CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); lastTicks = CoreTiming::GetTicks(); u32 currentPc = cpu->GetPC(); - u32 windowEnd = ptr->getWindowEnd(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); - u32 newAddress = currentPc+cpu->getInstructionSize(0); + u32 newAddress = currentPc+ptr->getInstructionSizeAt(currentPc); MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(cpu,currentPc); if (info.isBranch) { - if (newAddress == windowEnd-4) - ptr->scrollWindow(1); - else if (newAddress == windowEnd) - ptr->scrollWindow(2); + ptr->scrollStepping(newAddress); } else { bool scroll = true; if (currentMIPS->inDelaySlot) @@ -188,15 +182,16 @@ void CDisasm::stepInto() if (scroll) { - if (newAddress == windowEnd-4) - ptr->scrollWindow(1); - else if (newAddress == windowEnd) - ptr->scrollWindow(2); + ptr->scrollStepping(newAddress); } } - Core_DoSingleStep(); - Sleep(1); + for (u32 i = 0; i < (newAddress-currentPc)/4; i++) + { + Core_DoSingleStep(); + Sleep(1); + } + _dbg_update_(); ptr->gotoPC(); UpdateDialog(); @@ -218,11 +213,10 @@ void CDisasm::stepOver() // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); u32 currentPc = cpu->GetPC(); - u32 windowEnd = ptr->getWindowEnd(); MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(cpu,cpu->GetPC()); ptr->setDontRedraw(true); - u32 breakpointAddress = currentPc+cpu->getInstructionSize(0); + u32 breakpointAddress = currentPc+ptr->getInstructionSizeAt(currentPc); if (info.isBranch) { if (info.isConditional == false) @@ -241,19 +235,11 @@ void CDisasm::stepOver() breakpointAddress = info.branchTarget; } else { breakpointAddress = currentPc+2*cpu->getInstructionSize(0); - if (breakpointAddress == windowEnd-4) - ptr->scrollWindow(1); - else if (breakpointAddress == windowEnd) - ptr->scrollWindow(2); - else if (breakpointAddress == windowEnd+4) - ptr->scrollWindow(3); + ptr->scrollStepping(breakpointAddress); } } } else { - if (breakpointAddress == windowEnd-4) - ptr->scrollWindow(1); - else if (breakpointAddress == windowEnd) - ptr->scrollWindow(2); + ptr->scrollStepping(breakpointAddress); } SetDebugMode(false, true); @@ -525,35 +511,6 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) case IDC_MEMCHECK: SendMessage(m_hDlg,WM_COMMAND,ID_DEBUG_ADDBREAKPOINT,0); break; - case IDC_UPDATECALLSTACK: - { - HWND hDlg = m_hDlg; - HWND list = GetDlgItem(hDlg,IDC_CALLSTACK); - ComboBox_ResetContent(list); - - u32 pc = currentMIPS->pc; - u32 ra = currentMIPS->r[MIPS_REG_RA]; - DWORD addr = Memory::ReadUnchecked_U32(pc); - int count=1; - ComboBox_SetItemData(list, ComboBox_AddString(list, ConvertUTF8ToWString(symbolMap.GetDescription(pc)).c_str()), pc); - if (symbolMap.GetDescription(pc) != symbolMap.GetDescription(ra)) - { - ComboBox_SetItemData(list, ComboBox_AddString(list, ConvertUTF8ToWString(symbolMap.GetDescription(ra)).c_str()), ra); - count++; - } - //walk the stack chain - while (addr != 0xFFFFFFFF && addr!=0 && count++<20) - { - DWORD fun = Memory::ReadUnchecked_U32(addr+4); - const wchar_t *str = ConvertUTF8ToWString(symbolMap.GetDescription(fun)).c_str(); - if (wcslen(str) == 0) - str = L"(unknown)"; - ComboBox_SetItemData(list, ComboBox_AddString(list,str), fun); - addr = Memory::ReadUnchecked_U32(addr); - } - ComboBox_SetCurSel(list,0); - } - break; case IDC_GOTOPC: { @@ -569,15 +526,6 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) } break; - case IDC_BACKWARDLINKS: - { - HWND box = GetDlgItem(m_hDlg, IDC_FUNCTIONLIST); - int funcnum = symbolMap.GetSymbolNum(ListBox_GetItemData(box,ListBox_GetCurSel(box))); - if (funcnum!=-1) - symbolMap.FillListBoxBLinks(box,funcnum); - break; - } - case IDC_ALLFUNCTIONS: { symbolMap.FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); diff --git a/Windows/Debugger/Debugger_Lists.cpp b/Windows/Debugger/Debugger_Lists.cpp index 67e436e0fb..cd7cd5b5e7 100644 --- a/Windows/Debugger/Debugger_Lists.cpp +++ b/Windows/Debugger/Debugger_Lists.cpp @@ -129,6 +129,10 @@ void CtrlThreadList::showMenu(int itemIndex, const POINT &pt) void CtrlThreadList::GetColumnText(wchar_t* dest, int row, int col) { + if (row < 0 || row >= (int)threads.size()) { + return; + } + switch (col) { case TL_NAME: @@ -457,7 +461,7 @@ void CtrlBreakpointList::GetColumnText(wchar_t* dest, int row, int col) else wsprintf(dest,L"0x%08X",mc.end-mc.start); } else { - const char* sym = cpu->findSymbolForAddress(displayedBreakPoints_[index].addr); + const char* sym = symbolMap.GetLabelName(displayedBreakPoints_[index].addr); if (sym != NULL) { std::wstring s = ConvertUTF8ToWString(sym); @@ -618,6 +622,10 @@ bool CtrlStackTraceView::WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, L void CtrlStackTraceView::GetColumnText(wchar_t* dest, int row, int col) { + if (row < 0 || row >= (int)frames.size()) { + return; + } + switch (col) { case SF_ENTRY: @@ -625,7 +633,7 @@ void CtrlStackTraceView::GetColumnText(wchar_t* dest, int row, int col) break; case SF_ENTRYNAME: { - const char* sym = cpu->findSymbolForAddress(frames[row].entry); + const char* sym = symbolMap.GetLabelName(frames[row].entry); if (sym != NULL) { wcscpy(dest, ConvertUTF8ToWString(sym).c_str()); } else { diff --git a/Windows/Debugger/Debugger_VFPUDlg.cpp b/Windows/Debugger/Debugger_VFPUDlg.cpp index 67b4450cd1..beb8caf41e 100644 --- a/Windows/Debugger/Debugger_VFPUDlg.cpp +++ b/Windows/Debugger/Debugger_VFPUDlg.cpp @@ -168,8 +168,8 @@ BOOL CVFPUDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) for (int row = 0; row<4; row++) { - float val = mipsr4k.v[column*32+row+matrix*4]; - u32 hex = mipsr4k.vi[column*32+row+matrix*4]; + float val = mipsr4k.v[voffset[column*32+row+matrix*4]]; + u32 hex = mipsr4k.vi[voffset[column*32+row+matrix*4]]; switch (mode) { case 0: temp_len = sprintf_s(temp,"%f",val); break; diff --git a/Windows/Debugger/DumpMemoryWindow.cpp b/Windows/Debugger/DumpMemoryWindow.cpp index 4456eb2202..c5b1035a05 100644 --- a/Windows/Debugger/DumpMemoryWindow.cpp +++ b/Windows/Debugger/DumpMemoryWindow.cpp @@ -3,6 +3,7 @@ #include #include "Core/MemMap.h" #include "Windows/W32Util/ShellUtil.h" +#include "Core/Core.h" DumpMemoryWindow* DumpMemoryWindow::bp; @@ -77,10 +78,12 @@ INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, break; } + bool priorDumpWasStepping = Core_IsStepping(); + if (!priorDumpWasStepping) Core_EnableStepping(true); // If emulator isn't paused force paused state fwrite(Memory::GetPointer(bp->start), 1, bp->size, output); fclose(output); - - MessageBoxA(hwnd,"Done.","Error",MB_OK); + if (!priorDumpWasStepping) Core_EnableStepping(false); // If emulator wasn't paused before memory dump resume emulation automatically. + MessageBoxA(hwnd,"Done.","Information",MB_OK); EndDialog(hwnd,true); } break; @@ -97,7 +100,7 @@ INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, return FALSE; } -bool isInInterval(u32 start, u32 end, u32 value) +static bool isInInterval(u32 start, u32 end, u32 value) { return start <= value && value < end; } diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index edcf20903c..f25456d4e5 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -71,7 +71,6 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) // it's ugly, but .rc coordinates don't match actual pixels and it screws // up both the size and the aspect ratio - // TODO: Could be scrollable in case the framebuf is larger? Also should be better positioned. RECT frameRect; HWND frameWnd = GetDlgItem(m_hDlg,IDC_GEDBG_FRAME); @@ -117,6 +116,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) } CGEDebugger::~CGEDebugger() { + CleanupPrimPreview(); delete flags; delete lighting; delete textureState; @@ -140,8 +140,6 @@ void CGEDebugger::SetupPreviews() { } void CGEDebugger::UpdatePreviews() { - // TODO: Do something different if not paused? - wchar_t desc[256]; const GPUDebugBuffer *primaryBuffer = NULL; bool bufferResult = false; @@ -155,7 +153,7 @@ void CGEDebugger::UpdatePreviews() { case PRIMARY_FRAMEBUF: bufferResult = GPU_GetCurrentFramebuffer(primaryBuffer); if (bufferResult) { - _snwprintf(desc, ARRAY_SIZE(desc), L"Color: 0x%08x (%dx%d)", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight()); + _snwprintf(desc, ARRAY_SIZE(desc), L"Color: 0x%08x (%dx%d) fmt %i", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight(), state.FrameBufFormat()); } break; @@ -288,6 +286,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { return TRUE; case WM_CLOSE: + attached = false; + ResumeFromStepping(); + breakNext = BREAK_NONE; + Show(false); return TRUE; @@ -309,7 +311,6 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { break; case IDC_GEDBG_FBTABS: fbTabs->HandleNotify(lParam); - // TODO: Move this somewhere... if (attached && gpuDebug != NULL) { UpdatePreviews(); } @@ -345,6 +346,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case IDC_GEDBG_BREAKTEX: { + attached = true; if (!gpuDebug) { break; } @@ -367,7 +369,6 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, L""); SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L""); - // TODO: detach? Should probably have separate UI, or just on activate? ResumeFromStepping(); breakNext = BREAK_NONE; break; @@ -397,6 +398,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case WM_GEDBG_TOGGLEPCBREAKPOINT: { + attached = true; u32 pc = (u32)wParam; bool temp; bool isBreak = IsAddressBreakpoint(pc, temp); @@ -410,6 +412,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case WM_GEDBG_RUNTOWPARAM: { + attached = true; u32 pc = (u32)wParam; AddAddressBreakpoint(pc, true); SendMessage(m_hDlg,WM_COMMAND,IDC_GEDBG_RESUME,0); diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index de2ef79cad..6e968609e6 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -64,6 +64,7 @@ private: void SetupPreviews(); void UpdatePreviews(); void UpdatePrimPreview(u32 op); + void CleanupPrimPreview(); void UpdateSize(WORD width, WORD height); void SavePosition(); void SetBreakNext(BreakNextType type); diff --git a/Windows/GEDebugger/SimpleGLWindow.cpp b/Windows/GEDebugger/SimpleGLWindow.cpp index 0db94d4028..03e780dab9 100644 --- a/Windows/GEDebugger/SimpleGLWindow.cpp +++ b/Windows/GEDebugger/SimpleGLWindow.cpp @@ -224,6 +224,13 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) { } else if (fmt == FORMAT_565) { glfmt = GL_UNSIGNED_SHORT_5_6_5; components = GL_RGB; + } else if (fmt == FORMAT_4444_REV) { + glfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV; + } else if (fmt == FORMAT_5551_REV) { + glfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; + } else if (fmt == FORMAT_565_REV) { + glfmt = GL_UNSIGNED_SHORT_5_6_5_REV; + components = GL_RGB; } else if (fmt == FORMAT_16BIT) { glfmt = GL_UNSIGNED_SHORT; components = GL_RED; @@ -254,6 +261,33 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) { Redraw(); } +void SimpleGLWindow::GetContentSize(float &x, float &y, float &fw, float &fh) { + fw = (float)tw_; + fh = (float)th_; + x = 0.0f; + y = 0.0f; + + if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) { + float wscale = fw / w_, hscale = fh / h_; + + // Too wide, and width is the biggest problem, so scale based on that. + if (wscale > 1.0f && wscale > hscale) { + fw = (float)w_; + fh /= wscale; + } else if (hscale > 1.0f) { + fw /= hscale; + fh = (float)h_; + } + } + if (flags_ & RESIZE_CENTER) { + x = ((float)w_ - fw) / 2; + y = ((float)h_ - fh) / 2; + } + + x += offsetX_; + y += offsetY_; +} + void SimpleGLWindow::Redraw(bool andSwap) { DrawChecker(); @@ -277,27 +311,9 @@ void SimpleGLWindow::Redraw(bool andSwap) { glBindTexture(GL_TEXTURE_2D, tex_); glsl_bind(drawProgram_); - float fw = (float)tw_, fh = (float)th_; - float x = 0.0f, y = 0.0f; - if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) { - float wscale = fw / w_, hscale = fh / h_; - - // Too wide, and width is the biggest problem, so scale based on that. - if (wscale > 1.0f && wscale > hscale) { - fw = (float)w_; - fh /= wscale; - } else if (hscale > 1.0f) { - fw /= hscale; - fh = (float)h_; - } - } - if (flags_ & RESIZE_CENTER) { - x = ((float)w_ - fw) / 2; - y = ((float)h_ - fh) / 2; - } - - x += offsetX_; - y += offsetY_; + float fw, fh; + float x, y; + GetContentSize(x, y, fw, fh); const float pos[12] = {x,y,0, x+fw,y,0, x+fw,y+fh,0, x,y+fh,0}; static const float texCoords[8] = {0,0, 1,0, 1,1, 0,1}; @@ -325,9 +341,15 @@ void SimpleGLWindow::Clear() { void SimpleGLWindow::Begin() { Redraw(false); + + glDisableVertexAttribArray(drawProgram_->a_position); + glDisableVertexAttribArray(drawProgram_->a_texcoord0); } void SimpleGLWindow::End() { + glEnableVertexAttribArray(drawProgram_->a_position); + glEnableVertexAttribArray(drawProgram_->a_texcoord0); + Swap(); } diff --git a/Windows/GEDebugger/SimpleGLWindow.h b/Windows/GEDebugger/SimpleGLWindow.h index 310fec5746..4aae6d0223 100644 --- a/Windows/GEDebugger/SimpleGLWindow.h +++ b/Windows/GEDebugger/SimpleGLWindow.h @@ -25,10 +25,13 @@ struct SimpleGLWindow { static const PTCHAR windowClass; enum Format { - FORMAT_565 = 0, - FORMAT_5551 = 1, - FORMAT_4444 = 2, + FORMAT_565_REV = 0, + FORMAT_5551_REV = 1, + FORMAT_4444_REV = 2, FORMAT_8888 = 3, + FORMAT_565 = 4, + FORMAT_5551 = 5, + FORMAT_4444 = 6, FORMAT_FLOAT = 0x10, FORMAT_16BIT = 0x11, @@ -66,6 +69,24 @@ struct SimpleGLWindow { SwapBuffers(hDC_); } + int Width() { + return w_; + } + + int Height() { + return h_; + } + + int TexWidth() { + return tw_; + } + + int TexHeight() { + return th_; + } + + void GetContentSize(float &x, float &y, float &fw, float &fh); + static void RegisterClass(); protected: void SetupGL(); diff --git a/Windows/GEDebugger/TabDisplayLists.cpp b/Windows/GEDebugger/TabDisplayLists.cpp index a228b548f5..6ad1b1fdc7 100644 --- a/Windows/GEDebugger/TabDisplayLists.cpp +++ b/Windows/GEDebugger/TabDisplayLists.cpp @@ -33,6 +33,9 @@ CtrlDisplayListStack::CtrlDisplayListStack(HWND hwnd): GenericListControl(hwnd,d void CtrlDisplayListStack::GetColumnText(wchar_t* dest, int row, int col) { + if (row < 0 || row >= (int)ARRAY_SIZE(list.stack)) { + return; + } DisplayListStackEntry value = list.stack[row]; switch (col) @@ -77,6 +80,9 @@ CtrlAllDisplayLists::CtrlAllDisplayLists(HWND hwnd): GenericListControl(hwnd,all void CtrlAllDisplayLists::GetColumnText(wchar_t* dest, int row, int col) { + if (row < 0 || row >= (int)lists.size()) { + return; + } DisplayList& list = lists[row]; switch (col) diff --git a/Windows/GEDebugger/TabState.cpp b/Windows/GEDebugger/TabState.cpp index 51bf7bb5f2..895a938f50 100644 --- a/Windows/GEDebugger/TabState.cpp +++ b/Windows/GEDebugger/TabState.cpp @@ -64,6 +64,8 @@ enum CmdFormatType { CMD_FMT_TEXMODE, CMD_FMT_LOGICOP, CMD_FMT_TEXWRAP, + CMD_FMT_TEXFILTER, + CMD_FMT_TEXMAPMODE, }; struct TabStateRow { @@ -156,14 +158,12 @@ static const TabStateRow stateTextureRows[] = { { L"Tex V scale", GE_CMD_TEXSCALEV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex U offset", GE_CMD_TEXOFFSETU, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex V offset", GE_CMD_TEXOFFSETV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, - // TODO: Format. - { L"Tex mapping mode", GE_CMD_TEXMAPMODE, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex mapping mode", GE_CMD_TEXMAPMODE, CMD_FMT_TEXMAPMODE, GE_CMD_TEXTUREMAPENABLE }, // TODO: Format. { L"Tex shade srcs", GE_CMD_TEXSHADELS, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, { L"Tex mode", GE_CMD_TEXMODE, CMD_FMT_TEXMODE, GE_CMD_TEXTUREMAPENABLE }, { L"Tex format", GE_CMD_TEXFORMAT, CMD_FMT_TEXFMT, GE_CMD_TEXTUREMAPENABLE }, - // TODO: Format. - { L"Tex filtering", GE_CMD_TEXFILTER, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex filtering", GE_CMD_TEXFILTER, CMD_FMT_TEXFILTER, GE_CMD_TEXTUREMAPENABLE }, { L"Tex wrapping", GE_CMD_TEXWRAP, CMD_FMT_TEXWRAP, GE_CMD_TEXTUREMAPENABLE }, // TODO: Format. { L"Tex level/bias", GE_CMD_TEXLEVEL, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, @@ -614,6 +614,52 @@ void FormatStateRow(wchar_t *dest, const TabStateRow &info, u32 value, bool enab } break; + case CMD_FMT_TEXFILTER: + { + const char *textureFilters[] = { + "nearest", + "linear", + NULL, + NULL, + "nearest, mipmap nearest", + "linear, mipmap nearest", + "nearest, mipmap linear", + "linear, mipmap linear", + }; + if ((value & ~0x0107) == 0 && textureFilters[value & 7] != NULL) { + const int min = (value & 0x0007) >> 0; + const int mag = (value & 0x0100) >> 8; + swprintf(dest, L"min: %S, mag: %S", textureFilters[min], textureFilters[mag]); + } else { + swprintf(dest, L"%06x", value); + } + } + break; + + case CMD_FMT_TEXMAPMODE: + { + const char *uvGenModes[] = { + "tex coords", + "tex matrix", + "tex env map", + "unknown (tex coords?)", + }; + const char *uvProjModes[] = { + "pos", + "uv", + "normalized normal", + "normal", + }; + if ((value & ~0x0303) == 0) { + const int uvGen = (value & 0x0003) >> 0; + const int uvProj = (value & 0x0300) >> 8; + swprintf(dest, L"gen: %S, proj: %S", uvGenModes[uvGen], uvProjModes[uvProj]); + } else { + swprintf(dest, L"%06x", value); + } + } + break; + case CMD_FMT_FLAG: if ((value & ~1) == 0) { swprintf(dest, L"%d", value); @@ -633,6 +679,10 @@ void FormatStateRow(wchar_t *dest, const TabStateRow &info, u32 value, bool enab } void CtrlStateValues::GetColumnText(wchar_t *dest, int row, int col) { + if (row < 0 || row >= rowCount_) { + return; + } + switch (col) { case STATEVALUES_COL_NAME: wcscpy(dest, rows_[row].title); diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index 283844a185..b52217bc98 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -15,23 +15,139 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "math/lin/matrix4x4.h" +#include "gfx_es2/glsl_program.h" #include "Windows/GEDebugger/GEDebugger.h" #include "Windows/GEDebugger/SimpleGLWindow.h" #include "GPU/GPUInterface.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/GPUState.h" -// TODO: Possibly a shader here to do the transforms? +static const char preview_fs[] = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "void main() {\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.6);\n" + "}\n"; + +static const char preview_vs[] = +#ifndef USING_GLES2 + "#version 120\n" +#endif + "attribute vec4 a_position;\n" + "uniform mat4 u_viewproj;\n" + "void main() {\n" + " gl_Position = u_viewproj * a_position;\n" + "}\n"; + +static GLSLProgram *previewProgram = NULL; +static GLSLProgram *texPreviewProgram = NULL; + +static const GLuint glprim[8] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + // This is for RECTANGLES (see ExpandRectangles().) + GL_TRIANGLES, +}; + +static void BindPreviewProgram(GLSLProgram *&prog) { + if (prog == NULL) { + prog = glsl_create_source(preview_vs, preview_fs); + } + + glsl_bind(prog); +} + +static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) { + float tempu = a.u; + float tempv = a.v; + a.u = b.u; + a.v = b.v; + b.u = tempu; + b.v = tempv; +} + +static void RotateUVThrough(GPUDebugVertex v[4]) { + float x1 = v[2].x; + float x2 = v[0].x; + float y1 = v[2].y; + float y2 = v[0].y; + + if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) + SwapUVs(v[1], v[3]); +} + +static void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { + static std::vector newVerts; + static std::vector newInds; + + bool useInds = true; + size_t numInds = indices.size(); + if (indices.empty()) { + useInds = false; + numInds = count; + } + + // Will need 4 coords and 6 points per rectangle (currently 2 each.) + newVerts.resize(numInds * 2); + newInds.resize(numInds * 3); + + u16 v = 0; + GPUDebugVertex *vert = &newVerts[0]; + u16 *ind = &newInds[0]; + for (size_t i = 0, end = numInds; i < end; i += 2) { + const auto &orig_tl = useInds ? vertices[indices[i]] : vertices[i]; + const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1]; + + vert[0] = orig_br; + + // Top right. + vert[1] = orig_br; + vert[1].y = orig_tl.y; + vert[1].v = orig_tl.v; + + vert[2] = orig_tl; + + // Bottom left. + vert[3] = orig_br; + vert[3].x = orig_tl.x; + vert[3].u = orig_tl.u; + + // That's the four corners. Now process UV rotation. + if (throughMode) + RotateUVThrough(vert); + + // Build the two 3 point triangles from our 4 coordinates. + *ind++ = v + 0; + *ind++ = v + 1; + *ind++ = v + 2; + *ind++ = v + 3; + *ind++ = v + 0; + *ind++ = v + 2; + + vert += 4; + v += 4; + } + + std::swap(vertices, newVerts); + std::swap(indices, newInds); + count *= 3; +} void CGEDebugger::UpdatePrimPreview(u32 op) { const u32 prim_type = (op >> 16) & 0xFF; - const u32 count = op & 0xFFFF; + int count = op & 0xFFFF; if (prim_type >= 7) { ERROR_LOG(COMMON, "Unsupported prim type: %x", op); return; } if (!gpuDebug) { - ERROR_LOG(COMMON, "Invalid debugging environment, shutting down?", op); + ERROR_LOG(COMMON, "Invalid debugging environment, shutting down?"); return; } if (count == 0) { @@ -39,12 +155,76 @@ void CGEDebugger::UpdatePrimPreview(u32 op) { } const GEPrimitiveType prim = static_cast(prim_type); + static std::vector vertices; + static std::vector indices; + + if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { + ERROR_LOG(COMMON, "Vertex preview not yet supported"); + return; + } + + if (prim == GE_PRIM_RECTANGLES) { + ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); + } + + float fw, fh; + float x, y; frameWindow->Begin(); - // TODO: Get the coords, render on top of the texture and framebuffer previews. - // TODO: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);? + frameWindow->GetContentSize(x, y, fw, fh); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + glBindTexture(GL_TEXTURE_2D, 0); + glViewport(x, y, fw, fh); + glScissor(x, y, fw, fh); + BindPreviewProgram(previewProgram); + + float scale[] = { + 480.0f / (float)PSP_CoreParameter().renderWidth, + 272.0f / (float)PSP_CoreParameter().renderHeight, + }; + + Matrix4x4 ortho; + ortho.setOrtho(0, frameWindow->TexWidth() * scale[0], frameWindow->TexHeight() * scale[1], 0, -1, 1); + glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); + glEnableVertexAttribArray(previewProgram->a_position); + glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2); + + if (indices.empty()) { + glDrawArrays(glprim[prim], 0, count); + } else { + glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); + } + frameWindow->End(); texWindow->Begin(); + texWindow->GetContentSize(x, y, fw, fh); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + glBindTexture(GL_TEXTURE_2D, 0); + glViewport(x, y, fw, fh); + glScissor(x, y, fw, fh); + BindPreviewProgram(texPreviewProgram); + + ortho.setOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0); + glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); + glEnableVertexAttribArray(texPreviewProgram->a_position); + glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data()); + if (indices.empty()) { + glDrawArrays(glprim[prim], 0, count); + } else { + glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); + } + texWindow->End(); -} \ No newline at end of file +} + +void CGEDebugger::CleanupPrimPreview() { + glsl_destroy(previewProgram); + glsl_destroy(texPreviewProgram); +} diff --git a/Windows/Log.bat b/Windows/InfoLog.bat similarity index 90% rename from Windows/Log.bat rename to Windows/InfoLog.bat index 5ab79f2084..be96f6ca4e 100644 --- a/Windows/Log.bat +++ b/Windows/InfoLog.bat @@ -1,5 +1,5 @@ @echo off -set LOGFILE=ppsspp.log +set LOGFILE=ppsspplog.txt del "%LOGFILE%" 2> NUL if exist PPSSPPWindows64.exe ( diff --git a/Windows/PPSSPP.sln b/Windows/PPSSPP.sln index cd12576b10..d589d3d501 100644 --- a/Windows/PPSSPP.sln +++ b/Windows/PPSSPP.sln @@ -32,6 +32,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\Core\Core.vcxpro EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "native", "..\native\native.vcxproj", "{C4DF647E-80EA-4111-A0A8-218B1B711E18}" + ProjectSection(ProjectDependencies) = postProject + {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPPHeadless", "..\headless\Headless.vcxproj", "{EE9BD869-CAA3-447D-8328-294D90DE2C1F}" ProjectSection(ProjectDependencies) = postProject @@ -46,6 +49,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkirk", "..\ext\libkirk\l EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "..\unittest\UnitTests.vcxproj", "{37CBC214-7CE7-4655-B619-F7CEE16E3313}" ProjectSection(ProjectDependencies) = postProject + {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} {C4DF647E-80EA-4111-A0A8-218B1B711E18} = {C4DF647E-80EA-4111-A0A8-218B1B711E18} EndProjectSection EndProject diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index ed527c4a07..56c2bc6736 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -321,6 +321,7 @@ + @@ -366,6 +367,9 @@ + + + @@ -410,4 +414,4 @@ - \ No newline at end of file + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index fcb5c3b9b7..281af1571b 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -245,6 +245,9 @@ Windows\Debugger + + Other Platforms + @@ -287,6 +290,15 @@ Other Platforms + + Other Platforms + + + Other Platforms + + + Other Platforms + diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 09da666360..70171e0e7f 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -46,7 +46,6 @@ #include "Windows/Debugger/DebuggerShared.h" #include "Windows/Debugger/Debugger_Disasm.h" #include "Windows/Debugger/Debugger_MemoryDlg.h" -#include "Windows/InputBox.h" #include "Windows/DinputDevice.h" #include "Windows/XinputDevice.h" @@ -250,11 +249,6 @@ void WindowsHost::SaveSymbolMap() symbolMap.SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str(),".map").c_str()); } -void WindowsHost::AddSymbol(std::string name, u32 addr, u32 size, int type=0) -{ - symbolMap.AddSymbol(name.c_str(), addr, size, (SymbolType)type); -} - bool WindowsHost::IsDebuggingEnabled() { #ifdef _DEBUG @@ -282,27 +276,6 @@ void WindowsHost::UpdateConsolePosition() } } -bool WindowsHost::InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) -{ - std::string out; - if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) { - strcpy(outValue, out.c_str()); - return true; - } else { - return false; - } -} - -bool WindowsHost::InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) -{ - if (InputBox_GetWString(MainWindow::GetHInstance(), MainWindow::GetHWND(), title, defaultvalue, outvalue)) { - return true; - } else { - return false; - } -} - - // http://msdn.microsoft.com/en-us/library/aa969393.aspx HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathLink, LPCWSTR lpszDesc) { HRESULT hres; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index dc235f8edf..7bfdae872b 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -40,8 +40,6 @@ public: virtual void UpdateScreen(); void SetDebugMode(bool mode); - void AddSymbol(std::string name, u32 addr, u32 size, int type); - bool InitGL(std::string *error_message); void PollControllers(InputState &input_state); void ShutdownGL(); @@ -69,8 +67,6 @@ public: virtual void GoFullscreen(bool); - bool InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outlength); - bool InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue); std::shared_ptr keyboard; private: diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 801d60ec88..3c0b299a7e 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -46,6 +46,8 @@ #include "Core/SaveState.h" #include "Core/System.h" #include "Core/Config.h" +#include "Core/MIPS/JitCommon/JitCommon.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Windows/EmuThread.h" #include "resource.h" @@ -67,12 +69,32 @@ #include "Core/HLE/sceUtility.h" #include "GPU/Common/PostShader.h" +#include "Core/HLE/sceUmd.h" + #ifdef THEMES #include "XPTheme.h" #endif #define ENABLE_TOUCH 0 +int verysleepy__useSendMessage = 1; + +const UINT WM_VERYSLEEPY_MSG = WM_APP + 0x3117; +// Respond TRUE to a message with this param value to indicate support. +const WPARAM VERYSLEEPY_WPARAM_SUPPORTED = 0; +// Respond TRUE to a message wit this param value after filling in the addr name. +const WPARAM VERYSLEEPY_WPARAM_GETADDRINFO = 1; + +struct VerySleepy_AddrInfo +{ + // Always zero for now. + int flags; + // This is the pointer (always passed as 64 bits.) + unsigned long long addr; + // Write the name here. + wchar_t name[256]; +}; + extern std::map windowsTransTable; static RECT g_normalRC = {0}; static std::wstring windowTitle; @@ -372,6 +394,7 @@ namespace MainWindow void SetIngameMenuItemStates(const GlobalUIState state) { UINT menuEnable = state == UISTATE_INGAME ? MF_ENABLED : MF_GRAYED; + UINT umdSwitchEnable = state == UISTATE_INGAME && getUMDReplacePermit()? MF_ENABLED : MF_GRAYED; EnableMenuItem(menu, ID_FILE_SAVESTATEFILE, menuEnable); EnableMenuItem(menu, ID_FILE_LOADSTATEFILE, menuEnable); @@ -380,6 +403,7 @@ namespace MainWindow EnableMenuItem(menu, ID_TOGGLE_PAUSE, menuEnable); EnableMenuItem(menu, ID_EMULATION_STOP, menuEnable); EnableMenuItem(menu, ID_EMULATION_RESET, menuEnable); + EnableMenuItem(menu, ID_EMULATION_SWITCH_UMD, umdSwitchEnable); } // These are used as an offset @@ -468,7 +492,7 @@ namespace MainWindow void CreateShadersSubmenu() { I18NCategory *des = GetI18NCategory("DesktopUI"); - + I18NCategory *ps = GetI18NCategory("PostShaders"); const std::wstring key = ConvertUTF8ToWString(des->T("Postprocessing Shader")); HMENU optionsMenu = GetSubMenu(menu, MENU_OPTIONS); @@ -484,6 +508,8 @@ namespace MainWindow int item = ID_SHADERS_BASE + 1; int checkedStatus = -1; + const char *translatedShaderName = nullptr; + for (auto i = info.begin(); i != info.end(); ++i) { checkedStatus = MF_UNCHECKED; availableShaders.push_back(i->section); @@ -491,7 +517,9 @@ namespace MainWindow checkedStatus = MF_CHECKED; } - AppendMenu(shaderMenu, MF_STRING | MF_BYPOSITION | checkedStatus, item++, ConvertUTF8ToWString(i->name).c_str()); + translatedShaderName = ps->T(i->section.c_str()); + + AppendMenu(shaderMenu, MF_STRING | MF_BYPOSITION | checkedStatus, item++, ConvertUTF8ToWString(translatedShaderName).c_str()); } } @@ -547,7 +575,8 @@ namespace MainWindow // Emulation menu TranslateMenuItem(ID_TOGGLE_PAUSE, L"\tF8", "Pause"); TranslateMenuItem(ID_EMULATION_STOP, L"\tCtrl+W"); - TranslateMenuItem(ID_EMULATION_RESET, L"\tCtrl+B"); + TranslateMenuItem(ID_EMULATION_RESET, L"\tCtrl+B"); + TranslateMenuItem(ID_EMULATION_SWITCH_UMD, L"\tCtrl+U", "Switch UMD"); // Debug menu TranslateMenuItem(ID_DEBUG_LOADMAPFILE); @@ -795,7 +824,7 @@ namespace MainWindow void BrowseAndBoot(std::string defaultPath, bool browseDirectory) { std::string fn; - std::string filter = "PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*||"; + std::string filter = "All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"; for (int i=0; i<(int)filter.length(); i++) { if (filter[i] == '|') @@ -849,6 +878,21 @@ namespace MainWindow } } + void UmdSwitchAction() { + std::string fn; + std::string filter = "PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*||"; + + for (int i=0; i<(int)filter.length(); i++) { + if (filter[i] == '|') + filter[i] = '\0'; + } + + if (W32Util::BrowseForFileName(true, GetHWND(), L"Switch Umd", 0, ConvertUTF8ToWString(filter).c_str(), L"*.pbp;*.elf;*.iso;*.cso;",fn)) { + fn = ReplaceAll(fn, "\\", "/"); + __UmdReplace(fn); + } + } + LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // Only apply a factor > 1 in windowed mode. int factor = !IsZoomed(GetHWND()) && !g_Config.bFullScreen && g_Config.iWindowWidth < (480 + 80) ? 2 : 1; @@ -1140,6 +1184,9 @@ namespace MainWindow break; case ID_EMULATION_STOP: + if (Core_IsStepping()) + Core_EnableStepping(false); + Core_Stop(); NativeMessageReceived("stop", ""); Core_WaitInactive(); @@ -1150,6 +1197,9 @@ namespace MainWindow NativeMessageReceived("reset", ""); Core_EnableStepping(false); break; + case ID_EMULATION_SWITCH_UMD: + UmdSwitchAction(); + break; case ID_EMULATION_CHEATS: g_Config.bEnableCheats = !g_Config.bEnableCheats; @@ -1387,8 +1437,8 @@ namespace MainWindow case ID_EMULATION_SOUND: g_Config.bEnableSound = !g_Config.bEnableSound; - if(!g_Config.bEnableSound) { - if(!IsAudioInitialised()) + if (g_Config.bEnableSound) { + if (PSP_IsInited() && !IsAudioInitialised()) Audio_Init(); } break; @@ -1496,6 +1546,55 @@ namespace MainWindow } return 0; + case WM_VERYSLEEPY_MSG: + switch (wParam) { + case VERYSLEEPY_WPARAM_SUPPORTED: + return TRUE; + + case VERYSLEEPY_WPARAM_GETADDRINFO: + { + VerySleepy_AddrInfo *info = (VerySleepy_AddrInfo *)lParam; + const u8 *ptr = (const u8 *)info->addr; + if (MIPSComp::jit) { + JitBlockCache *blocks = MIPSComp::jit->GetBlockCache(); + u32 jitAddr = blocks->GetAddressFromBlockPtr(ptr); + + // Returns 0 when it's valid, but unknown. + if (jitAddr == 0) { + wcscpy_s(info->name, L"Jit::UnknownOrDeletedBlock"); + return TRUE; + } + if (jitAddr != (u32)-1) { + const char *label = symbolMap.GetDescription(jitAddr); + if (label != NULL) { + swprintf_s(info->name, L"Jit::%08x_%S", jitAddr, label); + } else { + swprintf_s(info->name, L"Jit::%08x", jitAddr); + } + return TRUE; + } + + // Perhaps it's in jit the dispatch runloop. + if (MIPSComp::jit->IsInDispatch(ptr)) { + wcscpy_s(info->name, L"Jit::RunLoopUntil"); + return TRUE; + } + } + if (gpu) { + std::string name; + if (gpu->DescribeCodePtr(ptr, name)) { + swprintf_s(info->name, L"GPU::%S", name.c_str()); + return TRUE; + } + } + } + return FALSE; + + default: + return FALSE; + } + break; + case WM_DROPFILES: { if (!EmuThread_Ready()) diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index 61078c9574..06cdbb04bc 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -67,4 +67,5 @@ namespace MainWindow void ToggleDebugConsoleVisibility(); void TranslateMenus(); void setTexScalingMultiplier(int level); + void UmdSwitchAction(); } diff --git a/Windows/main.cpp b/Windows/main.cpp index 9fe3efbae1..1cacd22379 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -30,7 +30,6 @@ #include "Common/LogManager.h" #include "Common/ConsoleListener.h" -#include "Common/Thread.h" #include "Commctrl.h" @@ -47,6 +46,7 @@ #include "Windows/Debugger/CtrlDisAsmView.h" #include "Windows/Debugger/CtrlMemView.h" #include "Windows/Debugger/CtrlRegisterList.h" +#include "Windows/InputBox.h" #include "Windows/WindowsHost.h" #include "Windows/main.h" @@ -156,9 +156,53 @@ std::string System_GetProperty(SystemProperty prop) { } } +void System_SendMessage(const char *command, const char *parameter) {} + +void EnableCrashingOnCrashes() +{ + typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); + typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); + const DWORD EXCEPTION_SWALLOWING = 0x1; + + HMODULE kernel32 = LoadLibraryA("kernel32.dll"); + tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, + "GetProcessUserModeExceptionPolicy"); + tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, + "SetProcessUserModeExceptionPolicy"); + if (pGetPolicy && pSetPolicy) + { + DWORD dwFlags; + if (pGetPolicy(&dwFlags)) + { + // Turn off the filter + pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); + } + } +} + +bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) +{ + std::string out; + if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) { + strcpy(outValue, out.c_str()); + return true; + } else { + return false; + } +} + +bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) +{ + if (InputBox_GetWString(MainWindow::GetHInstance(), MainWindow::GetHWND(), title, defaultvalue, outvalue)) { + return true; + } else { + return false; + } +} + int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { - Common::EnableCrashingOnCrashes(); + EnableCrashingOnCrashes(); wchar_t modulePath[MAX_PATH]; GetModuleFileName(NULL, modulePath, MAX_PATH); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 98f586b596..bb4fc54d84 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -389,6 +389,7 @@ BEGIN MENUITEM "Run", ID_TOGGLE_PAUSE MENUITEM "Stop", ID_EMULATION_STOP MENUITEM "Reset", ID_EMULATION_RESET + MENUITEM "Switch UMD", ID_EMULATION_SWITCH_UMD END POPUP "Debug" @@ -528,7 +529,7 @@ BEGIN MENUITEM "Kill Function", ID_DISASM_ADDHLE MENUITEM "Rename Function...", ID_DISASM_RENAMEFUNCTION MENUITEM "Remove Function", ID_DISASM_REMOVEFUNCTION - MENUITEM "Add Function here", ID_DISASM_ADDFUNCTION + MENUITEM "Add Function Here", ID_DISASM_ADDFUNCTION END POPUP "funclist" BEGIN diff --git a/Windows/resource.h b/Windows/resource.h index cce8701c05..6c74e1ed1c 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -12,7 +12,6 @@ #define IDC_STEPOVER 108 #define IDC_TABDATATYPE 109 #define IDC_CALLSTACK 110 -#define IDC_UPDATECALLSTACK 111 #define ID_MEMVIEW_GOTOINDISASM 112 #define ID_DISASM_DYNARECRESULTS 113 #define IDI_PPSSPP 115 @@ -105,7 +104,6 @@ #define IDC_GOTOLR 1070 #define IDC_GOTOINT 1071 #define IDC_MEMSORT 1073 -#define IDC_BACKWARDLINKS 1074 #define IDC_ALLFUNCTIONS 1075 #define IDC_RESULTS 1093 #define IDC_SYMBOLS 1097 @@ -299,6 +297,7 @@ #define ID_OPTIONS_LANGUAGE 40141 #define ID_MEMVIEW_COPYVALUE_16 40142 #define ID_MEMVIEW_COPYVALUE_32 40143 +#define ID_EMULATION_SWITCH_UMD 40144 // Dummy option to let the buffered rendering hotkey cycle through all the options. #define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500 diff --git a/Windows/version.rc b/Windows/version.rc index 7607ba040a..1de6505a37 100644 Binary files a/Windows/version.rc and b/Windows/version.rc differ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index b6a2208faa..3915c9e3aa 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,11 +1,11 @@ - + diff --git a/android/ab-ant.sh b/android/ab-ant.sh new file mode 100755 index 0000000000..cb3f172c46 --- /dev/null +++ b/android/ab-ant.sh @@ -0,0 +1,3 @@ +ant debug +adb install -r bin/PPSSPP-debug.apk +adb shell am start -n org.ppsspp.ppsspp/org.ppsspp.ppsspp.PpssppActivity \ No newline at end of file diff --git a/android/ab.cmd b/android/ab.cmd index a6a2cec17a..50eca5a072 100644 --- a/android/ab.cmd +++ b/android/ab.cmd @@ -2,6 +2,7 @@ xcopy ..\flash0 assets\flash0 /s /y xcopy ..\lang assets\lang /s /y xcopy ..\assets\shaders assets\shaders /s /y copy ..\assets\langregion.ini assets\langregion.ini +copy ..\assets\*.png assets SET NDK=C:\AndroidNDK SET NDK_MODULE_PATH=..;..\native\ext REM Need to force target-platform to android-9 to get access to OpenSL headers. diff --git a/android/ab.sh b/android/ab.sh index d8e0784063..22f80e3de2 100755 --- a/android/ab.sh +++ b/android/ab.sh @@ -2,4 +2,5 @@ cp -r ../flash0 assets cp -r ../lang assets cp -r ../assets/shaders assets cp ../assets/langregion.ini assets/langregion.ini +cp ../assets/*.png assets NDK_MODULE_PATH=..:../native/ext $NDK/ndk-build -j3 TARGET_PLATFORM=android-9 $* diff --git a/android/assets/rargray.png b/android/assets/rargray.png new file mode 100644 index 0000000000..90bdf104cd Binary files /dev/null and b/android/assets/rargray.png differ diff --git a/android/assets/ui_atlas.zim b/android/assets/ui_atlas.zim index 678341c96d..9a3d5babac 100644 Binary files a/android/assets/ui_atlas.zim and b/android/assets/ui_atlas.zim differ diff --git a/android/assets/zip.png b/android/assets/zip.png new file mode 100644 index 0000000000..beb6822e5f Binary files /dev/null and b/android/assets/zip.png differ diff --git a/android/build.xml b/android/build.xml index 9ece82a893..857125cf8d 100644 --- a/android/build.xml +++ b/android/build.xml @@ -37,6 +37,12 @@ + + + + +